Chooses the allocator the pool takes its blocks from: block_allocator if given, else context.allocator.
#import "Pool";
A bump allocator over blocks of memory that are reused or freed all together.
Procedures#
Returns nbytes bytes aligned to the pool's alignment, or null when the underlying allocator fails or the size is too large to represent.
Gives all memory back to the pool: oversized blocks are freed, ordinary blocks are kept for reuse (or freed too, with free_memblocks_on_reset).
Resets the pool and frees all its blocks through block_allocator. The pool can be used again; it takes new blocks on the next get.
How much the pool has handed out: the bytes used in ordinary blocks (including their headers and alignment padding) and the number of oversized blocks.
pool: Pool;
defer release(*pool);
get(*pool, 100);
bytes, oversized := calculate_used_memory(pool);
assert(bytes >= 100 && oversized == 0);
get(*pool, 100000);
bytes, oversized = calculate_used_memory(pool);
assert(oversized == 1);↗The Allocator_Proc for a pool: use it as Allocator.{ pool_allocator_proc, *pool }.
A small demonstration of the lifecycle: set up, allocate, reset, release. It exists as a smoke test and is not part of the API.
Types#
A bump allocator that hands out memory from large blocks and frees it all at once.
pool: Pool;
defer release(*pool);
numbers := cast(*int) get(*pool, 10 * size_of(int));
for 0..9 numbers[it] = it;
assert(numbers[9] == 9);
allocator := Allocator.{ pool_allocator_proc, *pool };
{
push_allocator(allocator);
text := copy_string("allocated from the pool"); // freed by reset, not by free
assert(text.count == 23);
}
reset(*pool); // everything above is gone↗