Arena storage pool: Difference between revisions

New post.
(New post.)
 
(11 intermediate revisions by 9 users not shown)
Line 1:
{{task}}[[Category:Encyclopedia]]
{{task}}
Dynamically allocated objects take their memory from a [[heap]]. The memory for an object is provided by an '''allocator''' which maintains the storage pool used for the [[heap]]. Often a call to allocator is denoted as
 
<lang ada>P := new T</lang>
Dynamically allocated objects take their memory from a [[heap]].
where T is the type of an allocated object and P is a [[reference]] to the object.
 
The memory for an object is provided by an '''allocator''' which maintains the storage pool used for the [[heap]].
 
Often a call to allocator is denoted as
<syntaxhighlight lang="ada">P := new T</syntaxhighlight>
where &nbsp; '''T''' &nbsp; is the type of an allocated object, &nbsp; and &nbsp; '''P''' &nbsp; is a [[reference]] to the object.
 
The storage pool chosen by the allocator can be determined by either:
* the object type T&nbsp; '''T'''
* the type of pointer &nbsp; '''P.'''
In the former case objects can be allocated only in one storage pool. In the latter case objects of the type can be allocated in any storage pool or on the [[stack]].
 
 
'''Task description'''<br>
In the former case objects can be allocated only in one storage pool.
The task is to show how allocators and user-defined storage pools are supported by the language. In particular:
 
# define an arena storage pool. An arena is a pool in which objects are allocated individually, but freed by groups.
In the latter case objects of the type can be allocated in any storage pool or on the [[stack]].
 
 
;Task:
The task is to show how allocators and user-defined storage pools are supported by the language.
 
In particular:
# define an arena storage pool. &nbsp; An arena is a pool in which objects are allocated individually, but freed by groups.
# allocate some objects (e.g., integers) in the pool.
 
 
Explain what controls the storage pool choice in the language.
<br><br>
 
=={{header|Ada}}==
In [[Ada]] the choice of storage pool is controlled by the type of the pointer. Objects pointed by anonymous access types are allocated in the default storage pool. Pool-specific pointer types may get a pool assigned to them:
<langsyntaxhighlight lang="ada">type My_Pointer is access My_Object;
for My_Pointer'Storage_Pool use My_Pool;</langsyntaxhighlight>
The following example illustrates implementation of an arena pool. Specification:
<langsyntaxhighlight lang="ada">with System.Storage_Elements; use System.Storage_Elements;
with System.Storage_Pools; use System.Storage_Pools;
 
Line 46 ⟶ 62:
Core : Storage_Array (1..Size);
end record;
end Arena_Pools;</langsyntaxhighlight>
Here is an implementation of the package:
<langsyntaxhighlight lang="ada">package body Arena_Pools is
procedure Allocate
( Pool : in out Arena;
Line 69 ⟶ 85:
return Pool.Size;
end Storage_Size;
end Arena_Pools;</langsyntaxhighlight>
The following is a test program that uses the pool:
<langsyntaxhighlight lang="ada">with Arena_Pools;
use Arena_Pools;
 
Line 85 ⟶ 101:
Z := new Integer;
Z.all := X.all + Y.all;
end Test_Allocator;</langsyntaxhighlight>
 
=={{header|C}}==
Line 92 ⟶ 108:
 
To use dynamic memory, the header for the standard library must be included in the module.
<syntaxhighlight lang ="c">#include <stdlib.h></langsyntaxhighlight>
Uninitialized memory is allocated using the malloc function. To obtain the amount of memory that needs to be allocated, sizeof is used. Sizeof is not a normal C function, it is evaluated by the compiler to obtain the amount of memory needed.
<langsyntaxhighlight lang="c">int *var = malloc(n*sizeof(int));
Typename *var = malloc(sizeof(Typename));
Typename *var = malloc(sizeof var[0]);</langsyntaxhighlight>
Since pointers to structures are needed so frequently, often a
typedef will define a type as being a pointer to the associated structure.
Once one gets used to the notation, programs are actually easier to read, as the
variable declarations don't include all the '*'s.
<langsyntaxhighlight lang="c">typedef struct mytypeStruct { .... } sMyType, *MyType;
 
MyType var = malloc(sizeof(sMyType));</langsyntaxhighlight>
The calloc() function initializes all allocated memory to zero. It is also often
used for allocating memory for arrays of some type.
<langsyntaxhighlight lang="c">/* allocate an array of n MyTypes */
MyType var = calloc(n, sizeof(sMyType));
 
MyType third = var+3; /* a reference to the 3rd item allocated */
 
MyType fourth = &var[4]; /* another way, getting the fourth item */</langsyntaxhighlight>
Freeing memory dynamically allocated from the heap is done by calling free().
<syntaxhighlight lang ="c">free(var);</langsyntaxhighlight>
One can allocate space on the stack using the alloca() function. You do not
free memory that's been allocated with alloca
<langsyntaxhighlight lang="c">Typename *var = alloca(sizeof(Typename));</langsyntaxhighlight>
An object oriented approach will define a function for creating a new object of a class.
In these systems, the size of the memory that needs to be allocated for an instance of the
Line 124 ⟶ 140:
Without using the standard malloc, things get a bit more complicated. For example, here is some code that implements something like it using the mmap system call (for Linux):
 
<langsyntaxhighlight lang="c">#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
Line 265 ⟶ 281:
return 0;
}</langsyntaxhighlight>
 
This is ''not'' how the real malloc is implemented on Linux. For one, memory leaks cannot be caught by Valgrind, and using a linked list to keep track of allocated blocks is very inefficient.
Line 274 ⟶ 290:
* You can replace the global allocation/deallocation routines, which are used by new/delete whenever there are no class specific functions available.
* You can write operator new/operator delete with additional arguments, both in a class and globally. To use those, you add those parameters after the keyword <code>new</code>, like
<langsyntaxhighlight lang="cpp">T* foo = new(arena) T;</langsyntaxhighlight>
* In addition, for objects in containers, there's a completely separate allocator interface, where the containers use an allocator object for allocating/deallocating memory.
 
The following code uses class-specific allocation and deallocation functions:
 
<langsyntaxhighlight lang="cpp">#include <cstdlib>
#include <cassert>
#include <new>
Line 382 ⟶ 398:
delete my_second_pool // also deallocates the memory for p6 and p7
 
} // Here my_pool goes out of scope, deallocating the memory for p1, p2 and p3</langsyntaxhighlight>
=={{header|Delphi}}==
{{libheader| Winapi.Windows}}
{{libheader| System.SysUtils}}
{{libheader| system.generics.collections}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program Arena_storage_pool;
 
Line 463 ⟶ 479:
Manager.Free;
readln;
end.</langsyntaxhighlight>
{{out}}
<pre>Allocate at addres 026788D0 with value of 5
Line 471 ⟶ 487:
Given automatic memory handling the only way to ask for memory in Erlang is when creating a process. Likewise the only way to manually return memory is by killing a process. So the pool could be built like this. The unit for memory is word, b.t.w.
 
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( arena_storage_pool ).
 
Line 502 ⟶ 518:
 
set( Pid, Key, Value ) -> Pid ! {set, Key, Value}.
</syntaxhighlight>
</lang>
 
=={{header|Fortran}}==
Line 511 ⟶ 527:
Thus, in a sense, a group of items for which storage has been allocated can have their storage released en-mass by exiting the routine. However, it is not the case that items A, B, C can be allocated in one storage "area" (say called "Able") and another group D, E in a second named area (say "Baker"), and that by discarding "Able" all its components would be de-allocated without the need to name them in tedious detail.
 
So, for example: <langsyntaxhighlight Fortranlang="fortran"> SUBROUTINE CHECK(A,N) !Inspect matrix A.
REAL A(:,:) !The matrix, whatever size it is.
INTEGER N !The order.
Line 523 ⟶ 539:
 
DEALLOCATE(TROUBLE) !Not necessary.
END SUBROUTINE CHECK !As TROUBLE is declared within CHECK.</langsyntaxhighlight>
 
Whereas previously a problem might not be solvable via the existing code because of excessive fixed-size storage requirements, now reduced demands can be made and those only for subroutines that are in action. Thus larger problems can be handled without agonising attempts to cut-to-fit, the usage for scratchpads such as B being particularly natural as in Algol from the 1960s. But on the other hand, a run might exhaust the available storage (either via the stack or via the heap) somewhere in the middle of job because its particular execution path made too many requests and the happy anticipation of results is instead met by a mess - and a bigger mess, because larger problems are being attempted.
 
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">
/' FreeBASIC admite tres tipos básicos de asignación de memoria:
- La asignación estática se produce para variables estáticas y globales.
La memoria se asigna una vez cuando el programa se ejecuta y persiste durante
toda la vida del programa.
- La asignación de pila se produce para parámetros de procedimiento y variables
locales. La memoria se asigna cuando se ingresa el bloque correspondiente y se
libera cuando se deja el bloque, tantas veces como sea necesario.
- La asignación dinámica es el tema de este artículo.
 
La asignación estática y la asignación de pila tienen dos cosas en común:
- El tamaño de la variable debe conocerse en el momento de la compilación.
- La asignación y desasignación de memoria ocurren automáticamente (cuando se
crea una instancia de la variable y luego se destruye). El usuario no puede
anticipar la destrucción de dicha variable.
 
La mayoría de las veces, eso está bien. Sin embargo, hay situaciones en las que
una u otra de estas restricciones causan problemas (cuando la memoria necesaria
depende de la entrada del usuario, el tamaño solo se puede determinar durante el
tiempo de ejecución).
 
1) Palabras clave para la asignación de memoria dinámica:
Hay dos conjuntos de palabras clave para la asignación / desasignación dinámica:
* Allocate / Callocate / Reallocate / Deallocate: para la asignación de
memoria bruta y luego la desasignación, para tipos simples predefinidos
o búferes de usuario.
* New / Delete: para asignación de memoria + construcción, luego
destrucción + desasignación.
Se desaconseja encarecidamente mezclar palabras clave entre estos dos
conjuntos cuando se gestiona un mismo bloque de memoria.
 
2) Variante usando Redim / Erase:
FreeBASIC también admite matrices dinámicas (matrices de longitud variable).
La memoria utilizada por una matriz dinámica para almacenar sus elementos se
asigna en tiempo de ejecución en el montón. Las matrices dinámicas pueden
contener tipos simples y objetos complejos.
Al usar Redim, el usuario no necesita llamar al Constructor / Destructor
porque Redim lo hace automáticamente cuando agrega / elimina un elemento.
Erase luego destruye todos los elementos restantes para liberar completamente
la memoria asignada a ellos.
 
'/
 
Type UDT
Dim As String S = "FreeBASIC" '' induce an implicit constructor and destructor
End Type
 
' 3 then 4 objects: Callocate, Reallocate, Deallocate, (+ .constructor + .destructor)
Dim As UDT Ptr p1 = Callocate(3, Sizeof(UDT)) '' allocate cleared memory for 3 elements (string descriptors cleared,
'' but maybe useless because of the constructor's call right behind)
For I As Integer = 0 To 2
p1[I].Constructor() '' call the constructor on each element
Next I
For I As Integer = 0 To 2
p1[I].S &= Str(I) '' add the element number to the string of each element
Next I
For I As Integer = 0 To 2
Print "'" & p1[I].S & "'", '' print each element string
Next I
Print
p1 = Reallocate(p1, 4 * Sizeof(UDT)) '' reallocate memory for one additional element
Clear p1[3], 0, 3 * Sizeof(Integer) '' clear the descriptor of the additional element,
'' but maybe useless because of the constructor's call right behind
p1[3].Constructor() '' call the constructor on the additional element
p1[3].S &= Str(3) '' add the element number to the string of the additional element
For I As Integer = 0 To 3
Print "'" & p1[I].S & "'", '' print each element string
Next I
Print
For I As Integer = 0 To 3
p1[I].Destructor() '' call the destructor on each element
Next I
Deallocate(p1) '' deallocate the memory
Print
 
' 3 objects: New, Delete
Dim As UDT Ptr p2 = New UDT[3] '' allocate memory and construct 3 elements
For I As Integer = 0 To 2
p2[I].S &= Str(I) '' add the element number to the string of each element
Next I
For I As Integer = 0 To 2
Print "'" & p2[I].S & "'", '' print each element string
Next I
Print
Delete [] p2 '' destroy the 3 element and deallocate the memory
Print
 
' 3 objects: Placement New, (+ .destructor)
Redim As Byte array(0 To 3 * Sizeof(UDT) - 1) '' allocate buffer for 3 elements
Dim As Any Ptr p = @array(0)
Dim As UDT Ptr p3 = New(p) UDT[3] '' only construct the 3 elements in the buffer (placement New)
For I As Integer = 0 To 2
p3[I].S &= Str(I) '' add the element number to the string of each element
Next I
For I As Integer = 0 To 2
Print "'" & p3[I].S & "'", '' print each element string
Next I
Print
For I As Integer = 0 To 2
p3[I].Destructor() '' call the destructor on each element
Next I
Erase array '' deallocate the buffer
Print
 
' 3 then 4 objects: Redim, Erase
Redim As UDT p4(0 To 2) '' define a dynamic array of 3 elements
For I As Integer = 0 To 2
p4(I).S &= Str(I) '' add the element number to the string of each element
Next I
For I As Integer = 0 To 2
Print "'" & p4(I).S & "'", '' print each element string
Next I
Print
Redim Preserve p4(0 To 3) '' resize the dynamic array for one additional element
p4(3).S &= Str(3) '' add the element number to the string of the additional element
For I As Integer = 0 To 3
Print "'" & p4(I).S & "'", '' print each element string
Next I
Print
Erase p4 '' erase the dynamic array
Print
Sleep
</syntaxhighlight>
 
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 583 ⟶ 726:
*j = 8
fmt.Println(*i + *j) // prints 15
}</langsyntaxhighlight>
{{output}}
<pre>
Line 598 ⟶ 741:
For example, you can define a class which allocates a pool of integers:
 
<langsyntaxhighlight lang="j">coclass 'integerPool'
require 'jmf'
create=: monad define
Line 624 ⟶ 767:
set=: adverb define
y memw m
)</langsyntaxhighlight>
 
With this script you can then create instances of this class, and use them. In this case, we will create a pool of three integers:
 
<langsyntaxhighlight lang="j"> pool0=: 3 conew 'integerPool'
x0=: alloc__pool0 0
x1=: alloc__pool0 0
Line 636 ⟶ 779:
x2 set__pool0 9
x0 get__pool0 + x1 get__pool0 + x2 get__pool0
24</langsyntaxhighlight>
 
Finally, the pool can be destroyed:
 
<syntaxhighlight lang ="j"> destroy__pool0 _</langsyntaxhighlight>
 
That said, using J's built-in support for integers (and for using them) usually results in better code.
 
=={{header|Java}}==
The Java programmer does not generally need to be concerned about memory management as the
Java Virtual Machine (JVM) automatically takes care of memory allocation for new objects,
and the releasing of that memory when an object is no longer needed. The latter operation
is accomplished by a garbage collector which runs in the background at intervals determined
by the JVM. The programmer can force a garbage collection by invoking the System.gc() method,
although this is not restricted to a single specified object.
The programmer can simulate an arena storage pool by using an array or one of the built-in
classes such as List, Map or Set. A simple example is given below.
<syntaxhighlight lang="java">
 
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
 
public final class ArenaStoragePool {
 
public static void main(String[] args) {
List<Object> storagePool = new ArrayList<Object>();
storagePool.addLast(42);
storagePool.addLast("Hello World");
storagePool.addFirst(BigInteger.ZERO);
System.out.println(storagePool);
storagePool = null;
System.gc();
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
[0, 42, Hello World]
</pre>
 
=={{header|Julia}}==
Line 650 ⟶ 830:
For example, a large 1000 X 1000 X 1000 matrix that will need to be changed repeatedly might be
allocated and initialized to zero with:
<langsyntaxhighlight lang="julia">
matrix = zeros(Float64, (1000,1000,1000))
# use matrix, then when done set variable to 0 to garbage collect the matrix:
matrix = 0 # large memory pool will now be collected when needed
</syntaxhighlight>
</lang>
 
=={{header|Kotlin}}==
Line 666 ⟶ 846:
 
To make life easier for the programmer when a number of allocations are required, it is possible for these to take place under the auspices of a MemScope object (an 'arena') which implements NativePlacement and automatically frees up the memory for these objects when they are no longer in scope. The process is automated by the memScoped function which takes a block as a parameter whose receiver is an implicit MemScope object. Here's a very simple example:
<langsyntaxhighlight lang="scala">// Kotlin Native v0.5
 
import kotlinx.cinterop.*
Line 679 ⟶ 859:
}
// native memory used by intVar1 & intVar2 is automatically freed when memScoped block ends
}</langsyntaxhighlight>
 
{{output}}
Line 685 ⟶ 865:
1 + 2 = 3
</pre>
=={{header|Lua}}==
Lua is a higher-level language with automatic allocation and garbage collection, and in most cases the programmer need not worry about the internal details - though some control over the strategy and scheduling of the garbage collector is exposed. ''(the reader is directed to the Lua Reference Manual if further internal specifics are desired, because it would be impractical to reproduce that material here, particularly since the details may vary among releases)''
 
If the goal is to simply create a collection of 'objects' that can be deleted en masse as a group, here is one possible approach that might suffice..
=={{header|Mathematica}}==
<syntaxhighlight lang="lua">pool = {} -- create an "arena" for the variables a,b,c,d
pool.a = 1 -- individually allocated..
pool.b = "hello"
pool.c = true
pool.d = { 1,2,3 }
pool = nil -- release reference allowing garbage collection of entire structure</syntaxhighlight>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
Mathematica does not allow stack/heap control, so all variables are defined on the heap. However, tags must be given a ''value'' for a meaningful assignment to take place.
<langsyntaxhighlight Mathematicalang="mathematica">f[x_] := x^2</langsyntaxhighlight>
 
=={{header|Nim}}==
Nim proposes two ways to manage memory. In the first one, objects are allocated on the heap using "new" and their deallocation is managed by the compiler and the runtime. In this case, objects are accessed via references ("ref").
 
 
The second method to allocate objects on the heap consists to do this the C way, using procedures "alloc" or "alloc0" to get blocks of memory. The deallocation is managed by the user who must call "dealloc" to free the memory. Using this method, objects are accessed via pointers ("ptr").
 
 
The preferred way is of course to use references which are safe. To allow a better fit to user needs, Nim proposes several options for automatic memory management. By specifying "--gc:refc" in the command line to launch the compilation, a garbage collector using reference counting is used. This is currently the default. Others options are "markAndSweep", "boehm" and "go" to use a different GC, each one having its pros and cons. "--gc:none" allows to deactivate totally automatic memory management which limits considerably the available functionnalities.
 
 
Since version 1.2, two more options are proposed. The first one, "--gc:arc" allows to choose the "arc" memory management which, in fact, is not a garbage collector. This is the most efficient option but it cannot free data structures containing cycles. The second option, "--gc:orc", allows to choose the "orc" memory management which is in fact "arc" with a cycle detection mechanism. It will probably become the default option in a future version.
 
 
In some cases, especially when a lot of similar objects must be allocated, it is a good idea to use a pool. It allows to allocate by blocks and to free globally.
 
 
Nim doesn’t propose any mechanism to manage such pools. There is an option "regions" which may be useful for this purpose but it is experimental and not documented. So, we will ignore it for now.
 
 
One way to manage pools consists to allocate blocks of memory and use some pointer arithmetic to return pointers to objects. The blocks may be allocated using "new" (and in this case will be freed automatically) or using "alloc" or "alloc0" and the deallocation must be required explicitely.
 
 
We provide here an example using blocks allocated by "new".
 
<syntaxhighlight lang="nim">
<lang Nim>
####################################################################################################
# Pool management.
Line 785 ⟶ 968:
test()
 
# No need to free the pool. This is done automatically as it has been allocated by "new".</langsyntaxhighlight>
 
{{out}}
Line 801 ⟶ 984:
There is no user-defined storage pool and it is not possible to explicitly destroy an object.
 
<langsyntaxhighlight Oforthlang="oforth">Object Class new: MyClass(a, b, c)
MyClass new</langsyntaxhighlight>
 
=={{header|ooRexx}}==
Line 815 ⟶ 998:
 
=={{header|OxygenBasic}}==
<langsyntaxhighlight lang="oxygenbasic">
'==============
Class ArenaPool
Line 847 ⟶ 1,030:
 
pool.empty
</syntaxhighlight>
</lang>
 
=={{header|PARI/GP}}==
Line 853 ⟶ 1,036:
 
PARI allocates objects on the PARI stack by default, but objects can be allocated on the heap if desired.
<langsyntaxhighlight Clang="c">pari_init(1<<20, 0); // Initialize PARI with a stack size of 1 MB.
GEN four = addii(gen_2, gen_2); // On the stack
GEN persist = gclone(four); // On the heap</langsyntaxhighlight>
 
=={{header|Pascal}}==
{{works with|Free_Pascal}}
The procedure New allocates memory on the heap:
<langsyntaxhighlight lang="pascal">procedure New (var P: Pointer);</langsyntaxhighlight>
 
The Pointer P is typed and the amount of memory allocated on the heap matches the type. Deallocation is done with the procedure Dispose. In ObjectPascal constructors and destructors can be passed to New and Dispose correspondingly. The following example is from the rtl docs of [[Free_Pascal]]
 
<langsyntaxhighlight lang="pascal">Program Example16;
{ Program to demonstrate the Dispose and New functions. }
Type
Line 896 ⟶ 1,079:
T^.i := 0;
Dispose ( T, Done );
end .</langsyntaxhighlight>
 
Instead of implicit specification of the amount of memory using a type, the explicit amount can directly specified with the procedure getmem (out p: pointer; Size: PtrUInt);
Line 905 ⟶ 1,088:
 
The simplest approach however is to rely on automatic memory management (as used by pGUI, and first implemented after arwen and win32lib were originally written):
<!--<syntaxhighlight lang="phix">(notonline)-->
<lang Phix>atom mem = allocate(size,true)</lang>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">mem</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">size</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
If the optional cleanup flag is non-zero (or true, as above), the memory is automatically released once it is no longer required
(ie when the variable mem drops out of scope or gets overwritten, assuming you have not made a copy of it elsewhere, which would
Line 912 ⟶ 1,098:
 
For completeness, here is a very simplistic arena manager, with just a single pool, not that it would be tricky to implement multiple pools:
<!--<syntaxhighlight lang="phix">(notonline)-->
<lang Phix>sequence ap = {}
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span>
function ap_allocate(integer size)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ap</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
-- allocate some memory and add it to the arena pool 'ap' for later release
<span style="color: #008080;">function</span> <span style="color: #000000;">ap_allocate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">size</span><span style="color: #0000FF;">)</span>
atom res = allocate(size)
<span style="color: #000080;font-style:italic;">-- allocate some memory and add it to the arena pool 'ap' for later release</span>
ap = append(ap,res)
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">size</span><span style="color: #0000FF;">)</span>
return res
<span style="color: #000000;">ap</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ap</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
procedure ap_free()
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
-- free all memory allocated in arena pool 'ap'
<span style="color: #008080;">procedure</span> <span style="color: #000000;">ap_free</span><span style="color: #0000FF;">()</span>
free(ap)
<span style="color: #000080;font-style:italic;">-- free all memory allocated in arena pool 'ap'</span>
ap = {}
<span style="color: #7060A8;">free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ap</span><span style="color: #0000FF;">)</span>
end procedure</lang>
<span style="color: #000000;">ap</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<!--</syntaxhighlight>-->
 
=={{header|PicoLisp}}==
Line 953 ⟶ 1,142:
 
As is common with high-level languages, Racket usually deals with memory automatically. By default, this means using a precise generational GC. However, when there's need for better control over allocation, we can use the <tt>malloc()</tt> function via the FFI, and the many variants that are provided by the GC:
<langsyntaxhighlight lang="racket">
(malloc 1000 'raw) ; raw allocation, bypass the GC, requires free()-ing
(malloc 1000 'uncollectable) ; no GC, for use with other GCs that Racket can be configured with
Line 963 ⟶ 1,152:
(malloc 1000 'atomic-interior) ; same for atomic chunks
(malloc-immobile-cell v) ; allocates a single cell that the GC will not move
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 997 ⟶ 1,186:
memory is available (these were written when real storage was a premium
during the early DOS days).
<langsyntaxhighlight lang="rexx">/*REXX doesn't have declarations/allocations of variables, */
/* but this is the closest to an allocation: */
 
Line 1,007 ⟶ 1,196:
stemmed_array.dog = stemmed_array.6000 / 2
 
drop stemmed_array.</langsyntaxhighlight>
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">#![feature(rustc_private)]
 
extern crate arena;
Line 1,036 ⟶ 1,225:
// The arena's destructor is called as it goes out of scope, at which point it deallocates
// everything stored within it at once.
}</langsyntaxhighlight>
 
=={{header|Scala}}==
Line 1,048 ⟶ 1,237:
 
The pool engine class itself (a metaclass):
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
oo::class create Pool {
superclass oo::class
Line 1,128 ⟶ 1,317:
return $cls
}
}</langsyntaxhighlight>
Example of how to use:
<langsyntaxhighlight lang="tcl">Pool create PoolExample {
variable int
 
Line 1,182 ⟶ 1,371:
}
puts ""
PoolExample clearPool</langsyntaxhighlight>
Produces this output (red text to <tt>stderr</tt>, black text to <tt>stdout</tt>):
<span style="color:red">Initializing ::oo::Obj4::Obj5 with 0
Line 1,214 ⟶ 1,403:
Finalizing ::oo::Obj4::Obj6 which held 10
Finalizing ::oo::Obj4::Obj7 which held 11</span>
 
=={{header|Wren}}==
Memory is managed automatically by Wren's VM which allocates memory for new objects and reclaims that memory when those objects are no longer used.
 
However, the built-in List class (a dynamic array) does give the programmer some control of memory in that a minimum size can be specified when the List is created. It's also possible to request a garbage collection (though not for a specific unused object) by calling the System.gc method.
 
We can therefore simulate an arena storage pool as follows.
<syntaxhighlight lang="wren">var arena = List.filled(5, 0) // allocate memory for 5 integers
for (i in 0..4) arena[i] = i // insert some integers
System.print(arena) // print them
arena = null // make arena eligible for garbage collection
System.gc() // request immediate garbage collection</syntaxhighlight>
 
{{out}}
<pre>
[0, 1, 2, 3, 4]
</pre>
 
=={{header|zkl}}==
Memory allocation "just happens", unreachable memory is recovered via garbage collection. The closest thing to explicit memory allocation is Data object, which is a bit bucket you can [optionally] set the size of upon creation. However, it grows as needed. The closest thing to "new" is the create method, which tells an object to create a new instance of itself. For this task:
<langsyntaxhighlight lang="zkl">var pool=List(); // pool could be any mutable container
pool.append(Data(0,1234)); // allocate mem blob and add to pool
pool=Void; // free the pool and everything in it.</langsyntaxhighlight>
 
{{omit from|6502 Assembly|Does not have controlled memory allocation.}}
{{omit from|8086 Assembly|Does not have controlled memory allocation.}}
{{omit from|68000 Assembly|Does not have controlled memory allocation.}}
{{omit from|Clojure}}
{{omit from|Erlang|Erlang does not have a program-controllable heap.}}
Line 1,232 ⟶ 1,441:
{{omit from|Oz|Oz does not have a program-controllable heap.}}
{{omit from|TI-89 BASIC|Does not have controlled memory allocation.}}
{{omit from|Z80 Assembly|Does not have controlled memory allocation.}}
871

edits