5#ifndef BITCOIN_SUPPORT_ALLOCATORS_POOL_H
6#define BITCOIN_SUPPORT_ALLOCATORS_POOL_H
72template <std::
size_t MAX_BLOCK_SIZE_BYTES, std::
size_t ALIGN_BYTES>
75 static_assert(ALIGN_BYTES > 0,
"ALIGN_BYTES must be nonzero");
76 static_assert((ALIGN_BYTES & (ALIGN_BYTES - 1)) == 0,
"ALIGN_BYTES must be a power of two");
86 static_assert(std::is_trivially_destructible_v<ListNode>,
"Make sure we don't need to manually call a destructor");
93 static_assert(
sizeof(
ListNode) <=
ELEM_ALIGN_BYTES,
"Units of size ELEM_SIZE_ALIGN need to be able to store a ListNode");
94 static_assert((MAX_BLOCK_SIZE_BYTES & (
ELEM_ALIGN_BYTES - 1)) == 0,
"MAX_BLOCK_SIZE_BYTES needs to be a multiple of the alignment.");
137 [[nodiscard]]
static constexpr bool IsFreeListUsable(std::size_t bytes, std::size_t alignment)
160 if (0 != remaining_available_bytes) {
219 void*
Allocate(std::size_t bytes, std::size_t alignment)
231 return std::exchange(
m_free_lists[num_alignments], next);
235 const std::ptrdiff_t round_bytes =
static_cast<std::ptrdiff_t
>(num_alignments *
ELEM_ALIGN_BYTES);
247 return ::operator
new (bytes, std::align_val_t{alignment});
253 void Deallocate(
void* p, std::size_t bytes, std::size_t alignment)
noexcept
264 ::operator
delete (p, std::align_val_t{alignment});
289template <
class T, std::
size_t MAX_BLOCK_SIZE_BYTES, std::
size_t ALIGN_BYTES = alignof(T)>
294 template <
typename U, std::
size_t M, std::
size_t A>
322 template <
typename U>
332 return static_cast<T*
>(
m_resource->Allocate(n *
sizeof(
T),
alignof(
T)));
349template <
class T1,
class T2, std::
size_t MAX_BLOCK_SIZE_BYTES, std::
size_t ALIGN_BYTES>
353 return a.resource() == b.resource();
#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
Forwards all allocations/deallocations to the PoolResource.
PoolResource< MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES > * m_resource
ResourceType * resource() const noexcept
PoolAllocator & operator=(const PoolAllocator &other) noexcept=default
void deallocate(T *p, size_t n) noexcept
Forwards each call to the resource.
PoolAllocator(const PoolAllocator &other) noexcept=default
PoolAllocator(ResourceType *resource) noexcept
Not explicit so we can easily construct it with the correct resource.
T * allocate(size_t n)
Forwards each call to the resource.
PoolAllocator(const PoolAllocator< U, MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES > &other) noexcept
A memory resource similar to std::pmr::unsynchronized_pool_resource, but optimized for node-based con...
PoolResource & operator=(const PoolResource &)=delete
void PlacementAddToList(void *p, ListNode *&node)
Replaces node with placement constructed ListNode that points to the previous node.
static constexpr std::size_t NumElemAlignBytes(std::size_t bytes)
How many multiple of ELEM_ALIGN_BYTES are necessary to fit bytes.
PoolResource(const PoolResource &)=delete
Disable copy & move semantics, these are not supported for the resource.
size_t ChunkSizeBytes() const
Size in bytes to allocate per chunk, currently hardcoded to a fixed size.
std::array< ListNode *, MAX_BLOCK_SIZE_BYTES/ELEM_ALIGN_BYTES+1 > m_free_lists
Single linked lists of all data that came from deallocating.
std::byte * m_available_memory_it
Points to the beginning of available memory for carving out allocations.
PoolResource & operator=(PoolResource &&)=delete
std::size_t NumAllocatedChunks() const
Number of allocated chunks.
static constexpr bool IsFreeListUsable(std::size_t bytes, std::size_t alignment)
True when it is possible to make use of the freelist.
void Deallocate(void *p, std::size_t bytes, std::size_t alignment) noexcept
Returns a block to the freelists, or deletes the block when it did not come from the chunks.
std::byte * m_available_memory_end
Points to the end of available memory for carving out allocations.
PoolResource(std::size_t chunk_size_bytes)
Construct a new PoolResource object which allocates the first chunk.
~PoolResource()
Deallocates all memory allocated associated with the memory resource.
static constexpr std::size_t ELEM_ALIGN_BYTES
Internal alignment value.
const size_t m_chunk_size_bytes
Size in bytes to allocate per chunk.
std::list< std::byte * > m_allocated_chunks
Contains all allocated pools of memory, used to free the data in the destructor.
PoolResource()
Construct a new Pool Resource object, defaults to 2^18=262144 chunk size.
PoolResource(PoolResource &&)=delete
void * Allocate(std::size_t bytes, std::size_t alignment)
Allocates a block of bytes.
void AllocateChunk()
Allocate one full memory chunk which will be used to carve out allocations.
Helper to get access to private parts of PoolResource.
constexpr auto CeilDiv(const Dividend dividend, const Divisor divisor)
Integer ceiling division (for unsigned values).
bool operator==(const PoolAllocator< T1, MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES > &a, const PoolAllocator< T2, MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES > &b) noexcept
The rebind struct here is mandatory because we use non type template arguments for PoolAllocator.
In-place linked list of the allocations, used for the freelist.