Files
cAI/cKit/Memory/c_Pool.c
T

140 lines
3.7 KiB
C
Raw Normal View History

2026-08-10 01:21:15 +08:00
#include <c_Pool.h>
#include <assert.h>
#include <stdlib.h>
#include "c_Alignment.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define FREE(x) do{ \
if(x){ \
free(x); \
(x) = NULL; \
} \
}while(0)
#define ALLOC(x) malloc(x)
#define NEW(p) (p)=ALLOC(sizeof(*(p)))
#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;
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 = 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) {
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_SUCCESS;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
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;
NEW(self->blockAllocator);
if (!self->blockAllocator) {
return C_ERR_NOMEM;
}
c_PoolBlockList_Init(self->blockAllocator);
return C_ERR_SUCCESS;
}
void c_Pool_Destroy(c_Pool_t* self) {
if (0==self->instanceCount) {
c_PoolBlockList_Destroy(self->blockAllocator);
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_SUCCESS) {
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) {
c_PoolBlockList_Destroy(self->blockAllocator);
FREE(self->blockAllocator);
self->instanceCount = 0;
}