3#include <bnb/utils/concurrency.hpp>
16 template<
typename T,
size_t MAX_ELEMENTS>
17 alignas(T)
inline static unsigned char static_pool[
sizeof(T) * MAX_ELEMENTS];
22 template<
typename T,
size_t MAX_ELEMENTS>
41 T* allocate(std::size_t n);
42 T* allocate(std::size_t n,
const std::nothrow_t&)
noexcept;
44 void deallocate(T* p, std::size_t n);
49 T* _allocate() noexcept;
50 bool _have_free() noexcept;
52 using free_slots_t = std::array<
size_t, MAX_ELEMENTS>;
54 inline static struct static_data_t
58 free_slots_t free_slots;
59 typename free_slots_t::iterator free_slots_end;
60 std::atomic_flag pool_lock;
61 unsigned char (&pool)[
sizeof(T) * MAX_ELEMENTS];
66 template<
typename T,
size_t MAX_ELEMENTS,
template<
typename>
class Alloc_fallback = std::allocator>
69 Alloc_fallback<T> alloc;
72 T* allocate(std::size_t n)
77 return alloc.allocate(n);
80 void deallocate(T* p, std::size_t n)
85 alloc.deallocate(p, n);
91 template<
typename T,
size_t MAX_ELEMENTS>
93 : pool(bnb::static_pool<T, MAX_ELEMENTS>)
96 std::generate(free_slots.begin(), free_slots.end(), [i]()
mutable { return i++; });
97 free_slots_end = free_slots.end();
102 template<
typename T,
size_t MAX_ELEMENTS>
103 inline T* static_pool_allocator<T, MAX_ELEMENTS>::allocate(std::size_t n)
105 spin_lock l(static_data.pool_lock);
107 if (!_have_free() || n > 1)
108 throw std::bad_alloc();
113 template<
typename T,
size_t MAX_ELEMENTS>
114 inline T* static_pool_allocator<T, MAX_ELEMENTS>::allocate(std::size_t n,
const std::nothrow_t&)
noexcept
116 spin_lock l(static_data.pool_lock);
118 if (!_have_free() || n > 1)
124 template<
typename T,
size_t MAX_ELEMENTS>
125 inline T* static_pool_allocator<T, MAX_ELEMENTS>::_allocate() noexcept
127 --static_data.free_slots_end;
128 const size_t slot = *static_data.free_slots_end;
130 void* mem = &static_data.pool[slot *
sizeof(T)];
132 return reinterpret_cast<T*
>(mem);
135 template<
typename T,
size_t MAX_ELEMENTS>
136 inline void static_pool_allocator<T, MAX_ELEMENTS>::deallocate(T* p, std::size_t n)
139 spin_lock l(static_data.pool_lock);
141 const size_t slot = (
reinterpret_cast<unsigned char*
>(p) -
reinterpret_cast<unsigned char*
>(static_data.pool)) /
sizeof(T);
142 *static_data.free_slots_end = slot;
143 ++static_data.free_slots_end;
146 template<
typename T,
size_t MAX_ELEMENTS>
147 inline bool static_pool_allocator<T, MAX_ELEMENTS>::_have_free() noexcept
149 if (static_data.free_slots_end == static_data.free_slots.begin())
154 template<
typename T,
size_t MAX_ELEMENTS>
155 inline bool static_pool_allocator<T, MAX_ELEMENTS>::is_mine(T* p)
157 if (
reinterpret_cast<char*
>(p) <
reinterpret_cast<char*
>(static_data.pool) ||
reinterpret_cast<char*
>(p) >
reinterpret_cast<char*
>(static_data.pool) +
sizeof(static_data.pool))
Doesn't support N allocs (std::vector)