core.tempalloc
This module will eventually be submitted for review and inclusion in core.memory. No synopsis is included since it will likely not be its own module. For now I named it core.tempalloc just to make DDoc generate Phobos-style documentation for it. This is only a provisional name. Author:David Simcha License:
Boost License 1.0
- Returns a new T[] allocated on the garbage collected heap without
initializing its elements. This can be a useful optimization if every
element will be immediately initialized.
Examples:
double[] arr = newVoid!double(100); assert(arr.length == 100);
- Allocates size bytes on the C heap, aligned on 16-byte boundaries. GC.addRange is called to allow the block to be scanned for pointers by the garbage collector iff shouldAddRange is true.
- Frees memory allocated by alignedMalloc. ptr must point to the start of the memory block. If shouldAddRange was true when alignedMalloc was called, this function also calls GC.removeRange on the block.
- TempAlloc is a memory allocator based on a thread-local segmented stack.
A segmented stack is similar to a regular stack in that memory is allocated
and freed in last in, first out order. When memory is requested from a
segmented stack, it first checks whether enough space is available in the
current segment, and if so increments the stack pointer and returns. If not,
a new segment is allocated. When memory is freed, the stack pointer is
decremented. If the last segment is no longer in use, it may be returned to
where it was allocated from or retained for future use.
TempAlloc has the following advantages compared to allocation on the
call stack:
1. Pointers to memory allocated on the TempAlloc stack are still
valid when the function they were allocated from returns.
Functions can be written to create and return data structures on the
TempAlloc stack.
2. Since it is a segmented stack, large allocations can be performed with no
danger of stack overflow errors.
It has the following advantages compared to heap allocation:
1. Both allocation and deallocation are extremely fast. Most allocations
consist of verifying enough space is available, incrementing a pointer and
a performing a few cheap bookkeeping operations. Most deallocations
consist decrementing a pointer and performing a few cheap bookkeeping
operations.
2. The segmented stack is thread-local, so synchronization is only needed
when a segment needs to be allocated or freed.
3. Fragmentation is not an issue when allocating memory on the
TempAlloc stack, though it can be an issue when trying to allocate
a new segment.
Note:
The first segment of the TempAlloc stack is allocated lazily, so no space is allocated in any thread that does not use TempAlloc.- Pushes the current stack position onto an internal bookkeeping stack. A call to frameFree frees all memory allocated since the last call to frameInit.
- Frees all memory allocated by TempAlloc since the last call to
frameInit. This can be used to free all TempAlloc memory
allocated within a function upon returning from that function.
Examples:
void useFrameInit() { // Mark the current position. TempAlloc.frameInit(); // Free all memory allocated by this function on exit. scope(exit) TempAlloc.frameFree(); // All of these will be freed when useFrameInit() exits. auto ptr1 = TempAlloc.malloc(3); auto ptr2 = TempAlloc.malloc(1); auto ptr3 = TempAlloc.malloc(4); }
- Allocates nbytes bytes on the TempAlloc stack. The last block allocated in the current thread can be freed by calling TempAlloc.free. The memory returned by this function is not scanned for pointers by the garbage collector unless GC.addRange is called.
- Frees the last block of memory allocated in the current thread by TempAlloc. Since all memory must be allocated and freed in last in first out order within a thread, there's no need to pass a pointer to the block being freed. This bookkeeping is handled internally.
- Returns the maximum number of bytes that may be allocated in the current stack segment.
- Allocates an array with size elements of type T on the TempAlloc
stack. For performance reasons, the returned array is not initialized. It
is not scanned for pointers by the garbage collector unless GC.addRange is
called.
Examples:
double[] arr = newStack!double(100); assert(arr.length == 100);
- Concatenates any number of arrays of the same type, placing results on
the TempAlloc stack. The returned array is not scanned for pointers
by the garbage collector unless GC.addRange is called.
Examples:
auto a = [1, 2, 3]; auto b = [4, 5, 6]; auto c = [7, 8, 9]; auto d = stackCat(a, b, c); assert(d == [1, 2, 3, 4, 5, 6, 7, 8, 9]);
- Copies range to an array. The array will be located on the
TempAlloc stack and not scanned for pointers by the garbage collector
under either of the following conditions:
1. std.traits.hasIndirections!(ElementType!R) is false, or
2. R is a builtin array. In this case range maintains pointers
to all elements at least until tempdup returns, preventing the
elements from being freed by the garbage collector. A similar assumption
cannot be made for ranges other than builtin arrays.
If neither condition is met, the array is returned on the C heap
and GC.addRange is called. In either case, TempAlloc.free or
TempAlloc.frameFree will free the array as if it had been allocated on
the TempAlloc stack.
Rationale:
The most common reason to call tempdup on an array is to modify its contents inside a function without affecting the caller's view. In this case range is not modified and prevents the elements from being freed by the garbage collector. - A convenience mixin, equivalent to:
TempAlloc.frameInit(); scope(exit) TempAlloc.frameFree();
Example:
void* useNewFrame() { // This will not be freed when useFrameInit() exits. auto ptr1 = TempAlloc.malloc(8); mixin(newFrame); // All of these will be freed when useFrameInit() exits. auto ptr2 = TempAlloc.malloc(3); auto ptr3 = TempAlloc.malloc(1); auto ptr4 = TempAlloc.malloc(4); // ptr1 is still valid after useNewFrame() exits. return ptr1; }