12 #include "allocator_base.hpp"
13 #include "internal/dynastic.hpp"
14 #include "internal/stack.hpp"
15 #include "internal/reallocator.hpp"
19 #pragma warning(disable : 4189)
22 #include <boost/lockfree/stack.hpp>
25 inline namespace v_100 {
45 template <
bool Shared,
class Allocator,
size_t MinSize,
size_t MaxSize,
unsigned PoolSize,
46 unsigned NumberOfBatchAllocations>
49 boost::lockfree::capacity<PoolSize >> ,
52 internal::dynastic<(MinSize == internal::DynasticDynamicSet ? internal::DynasticDynamicSet
54 internal::DynasticDynamicSet> _lowerBound;
55 internal::dynastic<(MaxSize == internal::DynasticDynamicSet ? internal::DynasticDynamicSet
57 internal::DynasticDynamicSet> _upperBound;
63 using allocator = Allocator;
64 static constexpr
unsigned pool_size = PoolSize;
65 static constexpr
unsigned number_of_batch_allocations = NumberOfBatchAllocations;
66 static constexpr
bool supports_truncated_deallocation = Allocator::supports_truncated_deallocation;
67 static constexpr
unsigned alignment = Allocator::alignment;
81 _lowerBound.value(minSize);
82 _upperBound.value(maxSize);
90 void *curBlock =
nullptr;
91 while (root_.pop(curBlock)) {
92 block oldBlock(curBlock, _upperBound.value());
93 allocator_.deallocate(oldBlock);
106 assert(_lowerBound.value() == internal::DynasticUndefined);
109 assert(_upperBound.value() == internal::DynasticUndefined);
112 _lowerBound.value(minSize);
113 _upperBound.value(maxSize);
120 return _lowerBound.value();
127 return _upperBound.value();
144 assert(_lowerBound.value() != ::std::numeric_limits<size_t>::max());
145 assert(_upperBound.value() != ::std::numeric_limits<size_t>::max());
147 if (_lowerBound.value() <= n && n <= _upperBound.value()) {
148 void *freeBlock =
nullptr;
150 if (root_.pop(freeBlock)) {
151 result.
ptr = freeBlock;
152 result.
length = _upperBound.value();
156 size_t blockSize = _upperBound.value();
157 if (supports_truncated_deallocation) {
160 auto batchAllocatedBlocks = allocator_.allocate(blockSize * NumberOfBatchAllocations);
162 if (batchAllocatedBlocks) {
164 for (
size_t i = 1; i < NumberOfBatchAllocations; i++) {
165 if (!root_.push(static_cast<char *>(batchAllocatedBlocks.ptr) + i * blockSize)) {
167 alb::block oldBlock(static_cast<char *>(batchAllocatedBlocks.ptr) + i * blockSize,
169 allocator_.deallocate(oldBlock);
173 result.
ptr = batchAllocatedBlocks.ptr;
174 result.
length = blockSize;
177 result = allocator_.allocate(blockSize);
180 for (
size_t i = 0; i < NumberOfBatchAllocations - 1; i++) {
181 result = allocator_.allocate(blockSize);
182 if (!root_.push(result.
ptr)) {
187 result = allocator_.allocate(blockSize);
202 if (internal::is_reallocation_handled_default(*
this, b, n)) {
214 return b && _lowerBound.value() <= b.length && b.length <= _upperBound.value();
224 if (root_.push(b.ptr)) {
228 allocator_.deallocate(b);
239 template <
class Allocator,
size_t MinSize,
size_t MaxSize,
size_t PoolSize = 1024,
240 size_t NumberOfBatchAllocations = 8>
242 NumberOfBatchAllocations>
261 template <
class Allocator,
size_t MinSize,
size_t MaxSize,
size_t PoolSize = 1024,
262 size_t NumberOfBatchAllocations = 8>
264 NumberOfBatchAllocations>
271 freelist(
size_t minSize,
size_t maxSize) noexcept
278 using namespace v_100;
void set_min_max(size_t minSize, size_t maxSize) noexcept
bool reallocate(block &b, size_t n) noexcept
size_t length
This describes the length of the reserved bytes.
block allocate(size_t n) noexcept
void * ptr
This points to the start address of the described memory block.
freelist_base(size_t minSize, size_t maxSize) noexcept
bool owns(const block &b) const noexcept
size_t min_size() const noexcept
size_t max_size() const noexcept
void deallocate(block &b) noexcept