14 pool_control *_control;
17 std::size_t _size = 0;
22 static pool_block *alloc(std::size_t sz) {
23 auto whole_size = sz +
sizeof(pool_block);
24 pool_block *b =
reinterpret_cast<pool_block *
>(::operator
new(whole_size));
29 static void dealloc(pool_block *blk) {
30 ::operator
delete(blk);
33 static pool_block *from_ptr(
void *ptr) {
34 auto me =
reinterpret_cast<pool_block *
>(ptr);
42 static thread_local pool_control instance;
44 pool_control() =
default;
45 pool_control(
const pool_control &) =
delete;
46 pool_control &operator=(
const pool_control &) =
delete;
53 pool_block *pick(std::size_t sz) {
56 if (_hashtable.empty()) {
57 if (!process_dropped()) {
58 out = pool_block::alloc(sz);
63 pool_block *& b = map_size(sz);
64 pool_block **lnk = &b;
66 while (p && p->_size != sz) {
76 }
while (process_dropped());
77 out = pool_block::alloc(sz);
83 pool_block *& map_size(std::size_t sz) {
84 auto idx = sz % _hashtable.size();
85 return _hashtable[idx];
88 void insert(pool_block *blk) {
90 auto &b = map_size(blk->_size);
96 bool process_dropped() {
97 pool_block *lst = _dropped.exchange(
nullptr, std::memory_order_relaxed);
98 if (!lst)
return false;
107 void drop(pool_block *blk) {
108 blk->_next = _dropped.load(std::memory_order_relaxed);
109 while (!_dropped.compare_exchange_weak(blk->_next, blk,std::memory_order_relaxed));
113 pool_block *lst = _dropped.exchange(
nullptr, std::memory_order_relaxed);
119 for (
auto &x: _hashtable) {
128 void check_resize() {
129 auto sz =_hashtable.size();
130 if (_keys * 2 >= sz) {
131 std::size_t newsz = next_prime_twice_than(std::max<std::size_t>(sz, 16));
132 std::vector<pool_block *> tmp(newsz,
nullptr);
133 std::swap(tmp, _hashtable);
146 std::vector<pool_block *> _hashtable;
147 std::atomic<pool_block *> _dropped = {};
148 std::size_t _keys = 0;
152 inline thread_local pool_control pool_control::instance;
179 static void *
alloc(std::size_t sz) {
180 sz = (sz + 0xF) & ~0xF;
181 auto blk = _details::pool_control::instance.pick(sz);
182 return blk->get_ptr();
190 static void dealloc(
void *ptr, std::size_t sz) {
191 sz = (sz + 0xF) & ~0xF;
192 auto blk = _details::pool_block::from_ptr(ptr);
193 if (blk->_size != sz)
throw std::runtime_error(
"coro::pool_alloc - invalid pointer for dealloc()");
194 auto control = blk->_control;
195 if (control != &_details::pool_control::instance) {
198 control->insert(blk);
static void * alloc(std::size_t sz)
allocate a block
static void dealloc(void *ptr, std::size_t sz)
deallocate block
A corutine allocator that caches unused frames in the pool.