18#ifndef REALM_CACHING_ALLOCATOR_H
19#define REALM_CACHING_ALLOCATOR_H
30 template <
typename T,
size_t N>
42 alignas(T)
char data[
sizeof(T)];
57 :
public IntrusiveList<Block, REALM_PMTA_USE(Block, block_link), Mutex> {
63 while(ptr !=
nullptr) {
64 Block *p = ptr->block_link.next;
65 ptr->block_link.next =
nullptr;
74 : num_alloced_chunks(0)
75 , free_chunk_head(&chunks[0])
88 assert((num_alloced_chunks.
load() == 0) &&
"Not all chunks have been freed!");
91 if(block_link.
next !=
nullptr) {
92 delete block_link.
next;
98 Chunk *old_head =
nullptr;
105 assert((expected_full_size >= 0) &&
106 "Tried to allocate from a block marked for reclaimation!");
110 assert((old_head !=
nullptr) &&
"Non-empty block with no free chunks!");
115 Chunk *next =
nullptr;
117 next = old_head->chunk_link.next;
120 old_head->chunk_link.next =
nullptr;
123 return &old_head->data;
125 bool free_obj(
void *p)
127 Chunk *chunk = get_chunk_from_obj(p);
131 chunk->chunk_link.next = old_head;
140 static Chunk *get_chunk_from_obj(
void *p)
142 return reinterpret_cast<Chunk *
>(
reinterpret_cast<uintptr_t
>(p) -
143 offsetof(Chunk, data));
146 static Block *get_block_from_obj(
void *p)
150 Chunk *chunk = get_chunk_from_obj(p);
151 return reinterpret_cast<Block *
>(
reinterpret_cast<uintptr_t
>(chunk - chunk->idx) -
152 offsetof(Block, chunks));
156 static typename Block::BlockList free_blocks;
160 static void release_block(Block *blk)
162 ssize_t old_num = blk->num_alloced_chunks.load();
164 !blk->num_alloced_chunks.compare_exchange_weak(old_num, -old_num))
177 static thread_local std::unique_ptr<Block,
decltype(&release_block)> current_block(
178 nullptr, release_block);
181 if(current_block !=
nullptr) {
182 obj = current_block->alloc_obj();
186 Block *newblk = free_blocks.pop_front();
187 if(newblk ==
nullptr) {
188 newblk =
new(std::nothrow) Block;
190 if(newblk !=
nullptr) {
191 obj = newblk->alloc_obj();
192 assert((obj !=
nullptr) &&
"Newly acquired block can't allocate!");
193 current_block.release();
194 current_block.reset(newblk);
202 Block *block = Block::get_block_from_obj(p);
203 if(block->free_obj(p)) {
206 block->num_alloced_chunks.store_release(0);
207 free_blocks.push_front(block);
212 template <
typename T,
size_t N>
213 typename CachingAllocator<T, N>::Block::BlockList CachingAllocator<T, N>::free_blocks;
Definition caching_allocator.h:31
static void free_obj(void *p)
Definition caching_allocator.h:200
static void * alloc_obj()
Definition caching_allocator.h:173
T value_type
Definition caching_allocator.h:33
@ BLOCK_SIZE
Definition caching_allocator.h:36
IntrusiveListLink< Block > head
Definition lists.h:97
bool compare_exchange_weak(T &expected, T newval)
T fetch_add_acqrel(T to_add)
bool compare_exchange(T &expected, T newval)
T load_acquire(void) const
T fetch_sub_acqrel(T to_sub)
#define REALM_PMTA_DEFN(structtype, membertype, name)
Definition lists.h:40
Definition activemsg.h:38
Definition caching_allocator.h:57
~BlockList(void)
Definition caching_allocator.h:58
Definition caching_allocator.h:41
IntrusiveListLink< Chunk > chunk_link
Definition caching_allocator.h:43
char data[sizeof(T)]
Definition caching_allocator.h:42
REALM_PMTA_DEFN(Chunk, IntrusiveListLink< Chunk >, chunk_link)
size_t idx
Definition caching_allocator.h:46
T * next
Definition lists.h:57