pbr-cpp-memory-pool 1.1.2
Fixed-block-size O(1) memory pool — C++17 with an ANSI C public surface
Loading...
Searching...
No Matches
memory_pool.h
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: MIT
3 * Copyright (c) 2026 Daniel Polo
4 */
5
6#ifndef IT_D4NP_MEMORYPOOL_MEMORY_POOL_H_
7#define IT_D4NP_MEMORYPOOL_MEMORY_POOL_H_
8
25#include <stddef.h>
26
27/*
28 * Diagnostics gate (ADR-0019 §1). A single macro controls the entire
29 * free-list diagnostic surface: the C accessors below and the C++
30 * `free_list_iterator.hpp` iterator. The default is build-type driven so
31 * the surface is available in debug builds and compiled out of release
32 * builds; an explicit definition (e.g. the CMake option
33 * PBR_MEMORY_POOL_ENABLE_DIAGNOSTICS, which defines it to 1 PUBLIC-ly on
34 * the library target) always wins. Walking the free list is O(free_count)
35 * and has no place on the allocation hot path — hence "disabled in release
36 * unless explicitly enabled" (ROADMAP 3.4).
37 */
38/* This is a preprocessor gate (it drives `#if` below and in the C++
39 * iterator header), so it must be a macro, not a constexpr constant — hence
40 * the cppcoreguidelines-macro-usage suppression around the definitions. */
41/* NOLINTBEGIN(cppcoreguidelines-macro-usage) */
42#ifndef PBR_MEMORY_POOL_DIAGNOSTICS
43#ifdef NDEBUG
44#define PBR_MEMORY_POOL_DIAGNOSTICS 0
45#else
46#define PBR_MEMORY_POOL_DIAGNOSTICS 1
47#endif
48#endif
49/* NOLINTEND(cppcoreguidelines-macro-usage) */
50
51/*
52 * Thread-safety mode (ADR-0020 §2). Selects how the implementation
53 * synchronizes the free-list head: NONE (no synchronization — the
54 * single-thread fast path, spec §2.4), MUTEX (a std::mutex), or LOCKFREE
55 * (an ABA-tagged Treiber-stack CAS). Bound at COMPILE TIME (a policy
56 * selected once, not a per-call branch) so the single-thread build pays
57 * nothing. Selected library-wide at build time via the
58 * PBR_MEMORY_POOL_THREAD_SAFETY macro (CMake option); the default is NONE.
59 * These are preprocessor constants (they drive `#if` selection in
60 * memory_pool.cpp), hence the cppcoreguidelines-macro-usage suppression.
61 */
62/* NOLINTBEGIN(cppcoreguidelines-macro-usage) */
63#define PBR_MEMORY_POOL_THREAD_SAFETY_NONE 0
64#define PBR_MEMORY_POOL_THREAD_SAFETY_MUTEX 1
65#define PBR_MEMORY_POOL_THREAD_SAFETY_LOCKFREE 2
66#ifndef PBR_MEMORY_POOL_THREAD_SAFETY
67#define PBR_MEMORY_POOL_THREAD_SAFETY PBR_MEMORY_POOL_THREAD_SAFETY_NONE
68#endif
69/* NOLINTEND(cppcoreguidelines-macro-usage) */
70
71#ifdef __cplusplus
72extern "C" {
73#endif
74
76/* The struct tag is snake_case to match the C convention for forward-
77 * declared opaque types; the .clang-tidy StructCase rule (CamelCase) is
78 * the right default for new C++ types, suppressed here for the C-interop
79 * boundary per the same rationale recorded at the definition site in
80 * memory_pool.cpp. */
81/* NOLINTNEXTLINE(readability-identifier-naming) */
82typedef struct memory_pool memory_pool_t;
83
110memory_pool_t* memory_pool_create(size_t block_size, size_t block_count);
111
134memory_pool_t* memory_pool_create_dynamic(size_t block_size, size_t block_count, size_t growth_factor);
135
149
174void memory_pool_free(memory_pool_t* pool, void* block);
175
189
211
226
241
242#if PBR_MEMORY_POOL_DIAGNOSTICS
243
258
272const void* memory_pool_debug_free_list_next(const memory_pool_t* pool, const void* current);
273
284
285#endif /* PBR_MEMORY_POOL_DIAGNOSTICS */
286
287#ifdef __cplusplus
288}
289#endif
290
291#endif
void * memory_pool_alloc(memory_pool_t *pool)
Allocate one block from pool in O(1).
struct memory_pool memory_pool_t
Opaque handle to a memory pool instance.
Definition memory_pool.h:82
void memory_pool_destroy(memory_pool_t *pool)
Destroy pool and release every byte of pre-allocated backing storage back to the operating system,...
size_t memory_pool_debug_free_count(const memory_pool_t *pool)
Diagnostics — count the free slots currently in pool's free list by walking it in O(free_count) (ADR-...
size_t memory_pool_metadata_bytes(const memory_pool_t *pool)
Report the per-pool metadata overhead in bytes (spec section 3.2 / ADR-0015).
memory_pool_t * memory_pool_create(size_t block_size, size_t block_count)
Create a memory pool able to vend block_count blocks of block_size bytes each.
size_t memory_pool_growths(const memory_pool_t *pool)
Report how many times pool has grown — i.e.
const void * memory_pool_debug_free_list_head(const memory_pool_t *pool)
Diagnostics — return the head of pool's implicit free list (ADR-0019 §2).
size_t memory_pool_block_size(const memory_pool_t *pool)
Report the configured per-block size of pool in bytes (ADR-0018 §3).
memory_pool_t * memory_pool_create_dynamic(size_t block_size, size_t block_count, size_t growth_factor)
Create a memory pool in dynamic-growth mode (spec section 2.2): when exhausted it acquires a new cont...
const void * memory_pool_debug_free_list_next(const memory_pool_t *pool, const void *current)
Diagnostics — given a free slot current obtained from memory_pool_debug_free_list_head or a previous ...
void memory_pool_free(memory_pool_t *pool, void *block)
Return a previously allocated block to pool in O(1).