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
typed_pool.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 Daniel Polo
3
4#ifndef IT_D4NP_MEMORYPOOL_TYPED_POOL_HPP_
5#define IT_D4NP_MEMORYPOOL_TYPED_POOL_HPP_
6
23
24#include <cstddef>
25#include <new>
26#include <optional>
27#include <type_traits>
28#include <utility>
29
30namespace it::d4np::memorypool {
31
55template <typename T>
56class TypedPool {
57 static_assert(!std::is_void_v<T>, "TypedPool<T>: T must be an object type; use Pool for raw void* blocks");
58 static_assert(!std::is_reference_v<T>, "TypedPool<T>: T must be an object type, not a reference");
59 static_assert(alignof(T) <= alignof(std::max_align_t),
60 "TypedPool<T>: over-aligned types are not supported — the pool guarantees "
61 "alignof(std::max_align_t) only (ADR-0009 §5, ADR-0017 §2)");
62
63public:
71 static constexpr std::size_t block_size() noexcept {
72 // UPPER_CASE per readability-identifier-naming.ConstexprVariableCase.
73 constexpr std::size_t FLOOR = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
74 constexpr std::size_t ALIGN = alignof(std::max_align_t);
75 return ((FLOOR + ALIGN - 1U) / ALIGN) * ALIGN;
76 }
77
91 explicit TypedPool(std::size_t block_count) : pool_(block_size(), block_count) {}
92
100 [[nodiscard]] static std::optional<TypedPool> make(std::size_t block_count) {
101 std::optional<Pool> pool = Pool::make(block_size(), block_count);
102 if (!pool.has_value()) {
103 return std::nullopt;
104 }
105 return {TypedPool{std::move(*pool)}};
106 }
107
119 [[nodiscard]] T* allocate() {
120 return static_cast<T*>(pool_.allocate());
121 }
122
130 [[nodiscard]] T* try_allocate() noexcept {
131 return static_cast<T*>(pool_.try_allocate());
132 }
133
142 void deallocate(T* block) noexcept {
143 pool_.deallocate(block);
144 }
145
160 template <typename... Args>
161 [[nodiscard]] T* construct(Args&&... args) {
162 void* const raw = pool_.allocate();
163 try {
164 // Placement new constructs in pool-owned storage — it does not
165 // allocate, so it transfers no ownership in the gsl sense.
166 // cppcoreguidelines-owning-memory misreads the `T*` return as a
167 // freshly allocated resource; the slot is owned by the pool and
168 // released through ::destroy / ::deallocate.
169 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
170 return ::new (raw) T(std::forward<Args>(args)...);
171 } catch (...) {
172 pool_.deallocate(raw);
173 throw;
174 }
175 }
176
186 void destroy(T* obj) noexcept {
187 if (obj == nullptr) {
188 return;
189 }
190 obj->~T();
191 pool_.deallocate(obj);
192 }
193
198 [[nodiscard]] memory_pool_t* native_handle() noexcept {
199 return pool_.native_handle();
200 }
201
207 [[nodiscard]] std::size_t metadata_bytes() const noexcept {
208 return pool_.metadata_bytes();
209 }
210
211private:
213 explicit TypedPool(Pool&& pool) noexcept : pool_(std::move(pool)) {}
214
215 Pool pool_;
216};
217
218} // namespace it::d4np::memorypool
219
220#endif // IT_D4NP_MEMORYPOOL_TYPED_POOL_HPP_
Owning, non-copyable, move-only wrapper around a memory_pool_t*.
void deallocate(void *block) noexcept
Return a previously allocated block to the pool in O(1).
void * allocate()
Allocate one block in O(1) — throwing verb (ADR-0016 §2).
memory_pool_t * native_handle() noexcept
void * try_allocate() noexcept
Allocate one block in O(1) — non-throwing verb (ADR-0016 §2).
std::size_t metadata_bytes() const noexcept
Report the per-pool metadata overhead in bytes (spec §3.2 / ADR-0015).
static std::optional< Pool > make(std::size_t block_size, std::size_t block_count)
Factory function returning an engaged std::optional<Pool> on successful construction or std::nullopt ...
Move-only, RAII, type-safe pool of fixed T-sized slots.
static constexpr std::size_t block_size() noexcept
The per-slot footprint in bytes — max(sizeof(T), sizeof(void*)) rounded up to the next multiple of al...
memory_pool_t * native_handle() noexcept
T * allocate()
Allocate one slot of uninitialized storage in O(1) — throwing verb (ADR-0016 §2).
T * try_allocate() noexcept
Allocate one slot of uninitialized storage in O(1) — non-throwing verb (ADR-0016 §2).
std::size_t metadata_bytes() const noexcept
Per-pool metadata overhead in bytes — forwards through Pool to memory_pool_metadata_bytes (spec §3....
TypedPool(std::size_t block_count)
Construct a typed pool with capacity for block_count slots.
static std::optional< TypedPool > make(std::size_t block_count)
Factory mirroring Pool::make (ADR-0011, restructured per ADR-0016 §3): failure as a value instead of ...
void destroy(T *obj) noexcept
Destroy a T obtained from construct and return its slot to the pool in O(1).
T * construct(Args &&... args)
Allocate a slot and placement-new a T into it — the object-lifetime verb (ADR-0017 §3).
void deallocate(T *block) noexcept
Return a storage slot obtained from allocate / try_allocate to the pool in O(1).
struct memory_pool memory_pool_t
Opaque handle to a memory pool instance.
Definition memory_pool.h:82
C++17 RAII wrapper around the C memory pool.