Template Class BucketPoolAllocator

Class Documentation

template<size_t B, size_t C, typename L = SpinLock, bool check_allocations = false>
class BucketPoolAllocator

Variable-size pool allocator with fixed-size buckets and embedded freelist.

BucketPoolAllocator is a variant of PoolAllocator for raw memory allocations (void*) up to a maximum bucket size. Instead of typed objects, it allocates fixed-size buckets that can hold variable-sized data. This is useful for small message queues, string buffers, or other variable-sized temporary allocations where the maximum size is known.

Like PoolAllocator, this uses an embedded freelist for O(1) allocation and deallocation, with the same LIFO reuse pattern. The constraint B >= sizeof(void*) exists for the same reason: free buckets must be large enough to store a pointer to the next free bucket.

The optional check_allocations template parameter enables allocation tracking using an atomic counter. When enabled, get_allocation_size() returns the number of currently allocated buckets, useful for debugging or telemetry.

Example - Small message queue:

// Pool for messages up to 256 bytes, max 100 messages
BucketPoolAllocator<256, 100> message_pool;

void send_message(const void* data, size_t size) {
    if (size > 256) {
        // Message too large, handle error
        return;
    }
    void* bucket = message_pool.alloc();
    std::memcpy(bucket, data, size);
    message_queue.push({bucket, size});
}

void process_messages() {
    while (!message_queue.empty()) {
        auto [bucket, size] = message_queue.pop();
        handle_message(bucket, size);
        message_pool.free(bucket);
    }
}

See also

PoolAllocator for typed object pools

See also

SpinLock for the default lock implementation

Template Parameters:
  • B – Bucket size in bytes. All allocations return B-byte buckets regardless of requested size. Must be >= sizeof(void*) for freelist embedding. Choose based on maximum expected allocation size.

  • C – Pool capacity (maximum number of buckets). Total pool size is B * C.

  • L – Lock type for thread safety. Defaults to SpinLock. Same semantics as PoolAllocator - use std::mutex for high contention.

  • check_allocations – If true, enables allocation tracking with atomic counter. Adds small overhead but allows querying allocated bucket count via get_allocation_size(). Defaults to false.

Public Functions

inline BucketPoolAllocator() noexcept
inline void *alloc()

Allocates a fixed-size bucket from the pool.

Returns a B-byte bucket regardless of how much space you actually need. The caller is responsible for not writing beyond their actual data size.

Throws:

std::bad_alloc – if pool is exhausted (all C buckets allocated)

Returns:

Pointer to a B-byte bucket

inline void free(void *p)

Frees the specified allocated pointer

Parameters:

p – The pointer to free

inline void clear()

Clears the entire pool allocator

inline size_t get_allocation_size() const

Returns the number of currently allocated buckets.

Only available when check_allocations template parameter is true. Uses atomic operations for thread-safe reading.

Returns:

Number of buckets currently allocated (not freed)

Public Static Attributes

static constexpr auto bucket_size = B

Size of each bucket in bytes.

static constexpr auto pool_size = C * B

Total size of the pool in bytes (C buckets * B bytes).