20260829 Redesign
This commit is contained in:
+161
@@ -0,0 +1,161 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user