162 lines
4.4 KiB
C
162 lines
4.4 KiB
C
#include <c_Pool.h>
|
|
#include <assert.h>
|
|
#include <c_Memory.h>
|
|
#include "c_Alignment.h"
|
|
#include "c_Macros.h"
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
#define DEFAULT_CHUNK_SIZE 10
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
|
|
typedef struct c_PoolBlockLink_t {
|
|
void* block;
|
|
struct c_PoolBlockLink_t* next;
|
|
}c_PoolBlockLink_t;
|
|
|
|
struct c_PoolBlockList_t{
|
|
c_PoolBlockLink_t* list;
|
|
};
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
void c_PoolBlockLink_Init(c_PoolBlockLink_t* self, void* p, c_PoolBlockLink_t* next) {
|
|
self->block = p;
|
|
self->next = next;
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
void c_PoolBlockList_Init(c_PoolBlockList_t* self) {
|
|
self->list = NULL;
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
void c_PoolBlockList_Destroy(c_PoolBlockList_t* self) {
|
|
if (!self) return;
|
|
while (self->list){
|
|
c_PoolBlockLink_t* q = self->list;
|
|
self->list = q->next;
|
|
C_FREE(q);
|
|
}
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
void* c_PoolBlockList_Alloc(c_PoolBlockList_t* self, c_size_t bytes) {
|
|
c_size_t block_size = bytes + sizeof(c_PoolBlockLink_t);
|
|
block_size = C_ALIGN_UPB(block_size, C_ALIGN_SIZE);
|
|
c_PoolBlockLink_t* p = C_ALLOC(block_size);
|
|
if (!p) {
|
|
return NULL;
|
|
}
|
|
c_PoolBlockLink_Init(p, p+1, self->list);
|
|
self->list = p;
|
|
return p->block;
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
c_err_t c_Pool_Replenish(c_Pool_t* self) {
|
|
if (!self || !self->blockAllocator) {
|
|
return C_ERR_PARAM;
|
|
}
|
|
c_size_t size = self->chunkSize * self->objSize;
|
|
uint8_t* start = (uint8_t*)c_PoolBlockList_Alloc(self->blockAllocator, size);
|
|
if (!start) return C_ERR_NOMEM;
|
|
uint8_t* last = &start[(self->chunkSize - 1) * self->objSize];
|
|
for (uint8_t* p = start; p<last; p+=self->objSize) {
|
|
((struct c_PoolLink_t*)p)->next = (struct c_PoolLink_t*)(p + self->objSize);
|
|
}
|
|
((struct c_PoolLink_t*)last)->next = NULL;
|
|
self->freelist = (struct c_PoolLink_t*)start;
|
|
return C_ERR_OK;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
c_err_t c_Pool_Init(c_Pool_t* self, int objSize, int chunkSize) {
|
|
self->freelist = 0;
|
|
self->objSize = objSize>=sizeof(struct c_PoolLink_t)?objSize:sizeof(struct c_PoolLink_t);
|
|
self->chunkSize = (chunkSize > 0)?chunkSize:DEFAULT_CHUNK_SIZE;
|
|
self->instanceCount = 0;
|
|
C_NEW(self->blockAllocator);
|
|
if (!self->blockAllocator) {
|
|
return C_ERR_NOMEM;
|
|
}
|
|
c_PoolBlockList_Init(self->blockAllocator);
|
|
|
|
return C_ERR_OK;
|
|
}
|
|
|
|
void c_Pool_Destroy(c_Pool_t* self) {
|
|
if (0==self->instanceCount) {
|
|
c_PoolBlockList_Destroy(self->blockAllocator);
|
|
C_FREE(self->blockAllocator);
|
|
self->freelist = NULL;
|
|
}
|
|
assert(0==self->instanceCount);
|
|
}
|
|
|
|
void* c_Pool_Alloc(c_Pool_t* self) {
|
|
if (!self->freelist) {
|
|
if (c_Pool_Replenish(self)!=C_ERR_OK) {
|
|
return NULL;
|
|
}
|
|
}
|
|
struct c_PoolLink_t* p = self->freelist;
|
|
self->freelist = p->next;
|
|
++self->instanceCount;
|
|
return p;
|
|
}
|
|
|
|
void c_Pool_Free(c_Pool_t* self, void* ptr) {
|
|
if (!self || !ptr) {
|
|
return;
|
|
}
|
|
|
|
struct c_PoolLink_t* p = (struct c_PoolLink_t*)ptr;
|
|
p->next = self->freelist;
|
|
self->freelist = p;
|
|
--self->instanceCount;
|
|
}
|
|
|
|
void c_Pool_DryUp(c_Pool_t* self) {
|
|
#if 0
|
|
c_PoolBlockList_Destroy(self->blockAllocator);
|
|
C_FREE(self->blockAllocator);
|
|
self->freelist = NULL;
|
|
self->instanceCount = 0;
|
|
#endif
|
|
|
|
|
|
if (!self) {
|
|
return;
|
|
}
|
|
|
|
/* 强制洗净 freelist 自由网 */
|
|
self->freelist = NULL;
|
|
self->instanceCount = 0;
|
|
|
|
if (!self->blockAllocator) {
|
|
return;
|
|
}
|
|
|
|
/* 🛠️ 链表反向全量闪放:将所有内部动态追加入驻的 Block 页一键逻辑全量清零,
|
|
这样所有的格子会被强制瞬间退回可用状态,而无需反复 free */
|
|
c_PoolBlockLink_t* curr = self->blockAllocator->list;
|
|
while (curr) {
|
|
unsigned char* byte_ptr = (unsigned char*)curr->block;
|
|
for (int i = 0; i < self->chunkSize; ++i) {
|
|
struct c_PoolLink_t* link = (struct c_PoolLink_t*)&byte_ptr[i * self->objSize];
|
|
link->next = self->freelist;
|
|
self->freelist = link;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|