parent
e9b697698a
commit
df5a06f119
3 changed files with 19 additions and 237 deletions
@ -1,210 +0,0 @@ |
|||||||
/***********************************************************************************
|
|
||||||
* Author: Sepehr Taghdisian (sep.tagh@gmail.com) |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef IMMEM_H |
|
||||||
#define IMMEM_H |
|
||||||
|
|
||||||
// Note: This file is meant to included only inside imgui.cpp
|
|
||||||
|
|
||||||
#ifndef IMGUI_INTERNAL_USE |
|
||||||
#error "This file is intented for internal use only (as include)" |
|
||||||
#endif |
|
||||||
|
|
||||||
/* Linked-List ************************************************************************************/ |
|
||||||
struct LinkedList |
|
||||||
{ |
|
||||||
LinkedList *next; |
|
||||||
LinkedList *prev; |
|
||||||
void *data; |
|
||||||
|
|
||||||
LinkedList() : next(NULL), prev(NULL) {} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
static void list_add(struct LinkedList** plist, struct LinkedList* item, void* data) |
|
||||||
{ |
|
||||||
item->next = (*plist); |
|
||||||
item->prev = NULL; |
|
||||||
if (*plist != NULL) |
|
||||||
(*plist)->prev = item; |
|
||||||
*plist = item; |
|
||||||
item->data = data; |
|
||||||
} |
|
||||||
|
|
||||||
static void list_addlast(struct LinkedList** plist, struct LinkedList* item, void* data) |
|
||||||
{ |
|
||||||
if (*plist != NULL) { |
|
||||||
struct LinkedList* last = *plist; |
|
||||||
while (last->next != NULL) last = last->next; |
|
||||||
last->next = item; |
|
||||||
item->prev = last; |
|
||||||
item->next = NULL; |
|
||||||
} else { |
|
||||||
*plist = item; |
|
||||||
item->prev = item->next = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
item->data = data; |
|
||||||
} |
|
||||||
|
|
||||||
static void list_remove(struct LinkedList** plist, struct LinkedList* item) |
|
||||||
{ |
|
||||||
if (item->next != NULL) item->next->prev = item->prev; |
|
||||||
if (item->prev != NULL) item->prev->next = item->next; |
|
||||||
if (*plist == item) *plist = item->next; |
|
||||||
item->next = item->prev = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
/* PoolAlloc **************************************************************************************/ |
|
||||||
template <typename T> |
|
||||||
class PoolAlloc |
|
||||||
{ |
|
||||||
private: |
|
||||||
LinkedList *m_blocks; /* first node of m_blocks */ |
|
||||||
int m_block_cnt; |
|
||||||
int m_items_max; /* maximum number of items allowed (per block) */ |
|
||||||
ImGui_MallocCallback m_malloc; |
|
||||||
ImGui_FreeCallback m_free; |
|
||||||
|
|
||||||
private: |
|
||||||
struct Block |
|
||||||
{ |
|
||||||
LinkedList node; /* linked-list node */ |
|
||||||
unsigned char *buffer; /* memory buffer that holds all objects */ |
|
||||||
void **ptrs; /* pointer references to the buffer */ |
|
||||||
int iter; /* iterator for current buffer position */ |
|
||||||
}; |
|
||||||
|
|
||||||
private: |
|
||||||
Block* create_block(int block_size) |
|
||||||
{ |
|
||||||
// Allocate in one call
|
|
||||||
size_t total_sz = |
|
||||||
sizeof(Block) + |
|
||||||
sizeof(T)*block_size + |
|
||||||
sizeof(void*)*block_size; |
|
||||||
unsigned char *buff = (unsigned char*)m_malloc(total_sz); |
|
||||||
if (buff == NULL) |
|
||||||
return NULL; |
|
||||||
memset(buff, 0x00, total_sz); |
|
||||||
|
|
||||||
Block *block = (Block*)buff; |
|
||||||
buff += sizeof(Block); |
|
||||||
block->buffer = buff; |
|
||||||
buff += sizeof(T)*block_size; |
|
||||||
block->ptrs = (void**)buff; |
|
||||||
|
|
||||||
// Assign pointer refs
|
|
||||||
for (int i = 0; i < block_size; i++) |
|
||||||
block->ptrs[block_size-i-1] = block->buffer + i*sizeof(T); |
|
||||||
block->iter = block_size; |
|
||||||
|
|
||||||
/* add to linked-list of the pool */ |
|
||||||
list_addlast(&m_blocks, &block->node, block); |
|
||||||
m_block_cnt++; |
|
||||||
return block; |
|
||||||
} |
|
||||||
|
|
||||||
void destroy_block(Block *block) |
|
||||||
{ |
|
||||||
list_remove(&m_blocks, &block->node); |
|
||||||
m_free(block); |
|
||||||
m_block_cnt--; |
|
||||||
} |
|
||||||
|
|
||||||
public: |
|
||||||
PoolAlloc() |
|
||||||
{ |
|
||||||
m_blocks = NULL; |
|
||||||
m_block_cnt = 0; |
|
||||||
m_items_max = 0; |
|
||||||
m_malloc = NULL; |
|
||||||
m_free = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
bool create(int block_sz, ImGui_MallocCallback malloc_fn, ImGui_FreeCallback free_fn) |
|
||||||
{ |
|
||||||
m_items_max = block_sz; |
|
||||||
m_malloc = malloc_fn; |
|
||||||
m_free = free_fn; |
|
||||||
|
|
||||||
// First block
|
|
||||||
Block *block = create_block(block_sz); |
|
||||||
if (block == NULL) { |
|
||||||
destroy(); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
void destroy() |
|
||||||
{ |
|
||||||
LinkedList* node = m_blocks; |
|
||||||
while (node != NULL) { |
|
||||||
LinkedList* next = node->next; |
|
||||||
destroy_block((Block*)node->data); |
|
||||||
node = next; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
T* alloc() |
|
||||||
{ |
|
||||||
LinkedList* node = m_blocks; |
|
||||||
|
|
||||||
while (node != NULL) { |
|
||||||
Block *block = (Block*)node->data; |
|
||||||
if (block->iter > 0) |
|
||||||
return (T*)block->ptrs[--block->iter]; |
|
||||||
|
|
||||||
node = node->next; |
|
||||||
} |
|
||||||
|
|
||||||
/* couldn't find a free block, create a new one */ |
|
||||||
Block *block = create_block(m_items_max); |
|
||||||
if (block == NULL) |
|
||||||
return NULL; |
|
||||||
|
|
||||||
return (T*)block->ptrs[--block->iter]; |
|
||||||
} |
|
||||||
|
|
||||||
void free(T *ptr) |
|
||||||
{ |
|
||||||
// find the block that pointer belongs to, and free the pointer from that block
|
|
||||||
LinkedList *node = m_blocks; |
|
||||||
int buffer_sz = m_items_max*sizeof(T); |
|
||||||
unsigned char *u8ptr = (unsigned char*)ptr; |
|
||||||
|
|
||||||
while (node != NULL) { |
|
||||||
Block *block = (Block*)node->data; |
|
||||||
if (u8ptr >= block->buffer && u8ptr < (block->buffer + buffer_sz)) { |
|
||||||
IM_ASSERT(block->iter != m_items_max); |
|
||||||
block->ptrs[block->iter++] = ptr; |
|
||||||
return; |
|
||||||
} |
|
||||||
node = node->next; |
|
||||||
} |
|
||||||
|
|
||||||
// Memory block does not belong to the pool?!
|
|
||||||
IM_ASSERT(0); |
|
||||||
} |
|
||||||
|
|
||||||
void clear() |
|
||||||
{ |
|
||||||
int block_size = m_items_max; |
|
||||||
LinkedList* node = m_blocks; |
|
||||||
while (node != NULL) { |
|
||||||
Block *block = (Block*)node->data; |
|
||||||
|
|
||||||
/* only re-assign pointer references to buffer */ |
|
||||||
for (int i = 0; i < block_size; i++) |
|
||||||
block->ptrs[block_size-i-1] = block->buffer + i*sizeof(T); |
|
||||||
block->iter = block_size; |
|
||||||
|
|
||||||
node = node->next; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // IMMEM_H
|
|
Loading…
Reference in New Issue