Template Class BufferedAllocator

Class Documentation

template<unsigned int N>
class BufferedAllocator

Multi-buffered allocator wrapping N StackAllocators for round-robin frame buffering.

BufferedAllocator manages N independent StackAllocators and rotates through them using swap_buffers(). This enables safe multi-frame data persistence, essential for scenarios where frame N data must remain valid while frame N+1 is prepared, such as GPU resource updates that execute asynchronously.

Each swap_buffers() call advances to the next allocator (wrapping at N) and clears it, ensuring old data from N frames ago is freed. With double buffering (N=2), frame N writes to buffer 0 while GPU reads frame N-1 from buffer 1. With triple buffering (N=3), an additional frame of overlap is provided for even more CPU/GPU parallelism.

All allocation and deallocation operations (alloc(), free()) operate on the current buffer selected by the internal stack_index. Use get_allocator(index) to access specific buffers if needed.

Example - Double-buffered GPU resource updates:

BufferedAllocator<2> gpu_staging(4 * 1024 * 1024);  // 4MB per buffer

void render_frame() {
    // Allocate staging data in current buffer
    auto* vertices = gpu_staging.alloc<Vertex>(vertex_count);
    auto* uniforms = gpu_staging.alloc<UniformData>();

    // Fill data and upload to GPU
    fill_vertex_buffer(vertices, vertex_count);
    gpu_upload(vertices, sizeof(Vertex) * vertex_count);

    // Submit GPU commands referencing this buffer's data
    submit_render_commands();

    // Swap to next buffer (clears it, but previous buffer remains valid
    // for GPU to read while we prepare the next frame)
    gpu_staging.swap_buffers();
}

Example - Triple buffering for maximum overlap:

BufferedAllocator<3> triple_buffer(2 * 1024 * 1024);
// Frame N-2 data being read by GPU
// Frame N-1 data in flight
// Frame N being written by CPU

See also

StackAllocator for the underlying allocator being buffered

Template Parameters:

N – Number of buffers to rotate through. Must be at least 2. Common values are 2 (double buffering) or 3 (triple buffering).

Public Functions

BufferedAllocator() = default

Default constructor creating N stack allocators with default size.

inline explicit BufferedAllocator(const size_t buffer_size)

Constructs N stack allocators each with the specified buffer size.

Parameters:

buffer_size – Size in bytes for each of the N internal StackAllocators

inline void swap_buffers()

Advances to the next buffer in round-robin sequence and clears it.

This increments the internal stack_index (wrapping at N) and clears the newly selected buffer, making it ready for the next frame’s allocations. Previous buffers remain untouched, preserving their data for in-flight operations (like GPU reads).

Call this once per frame at frame boundaries to rotate buffers.

inline void *alloc(size_t size)

Allocates a given size from the current stack

Parameters:

size – The size to allocate

Returns:

A pointer to the beginning of the allocated memory

template<typename T, typename ...Args>
inline T *alloc(Args&&... args)

Allocates memory and constructs an object of type T

Template Parameters:
  • T – The type of object to allocate

  • Args – Constructor argument types

Parameters:

args – Constructor arguments

Returns:

Pointer to the new object

inline void free(void *p)

frees an allocation made by the current stack allocator.

Parameters:

p – The pointer to the memory to free. This must be a pointer allocated by the current stack allocator.

template<typename T>
inline void free(T *p)

Destroys and frees an object of type T

Template Parameters:

T – The type of object to free

Parameters:

p – Pointer to the object

inline void clear()

Clears the current stack allocator.

inline void clear(size_t)

Clears a specific stack allocator by index. Note: Current implementation ignores the parameter and clears the current allocator.

inline StackAllocator &get_current_allocator()

Gets the current stack allocator.

Returns:

the current stack allocator

inline StackAllocator &get_allocator(size_t index)

Gets a specific stack allocator by index.

Parameters:

index – The index of the stack allocator to get. Must be in the range [0, N-1].

Returns:

the stack allocator at the specified index