You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.3 KiB
107 lines
3.3 KiB
// memory_pool.c |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <stdint.h> |
|
#include "memory_pool.h" |
|
#include "mem.h" |
|
|
|
static size_t g_total_free = 0; |
|
|
|
size_t memory_pool_get_total_free_blocks(void) { |
|
return g_total_free; |
|
} |
|
|
|
// Инициализировать пул памяти |
|
struct memory_pool* memory_pool_init(size_t object_size) { |
|
struct memory_pool* pool = u_calloc(1, sizeof(struct memory_pool)); |
|
if (!pool) { |
|
return NULL; |
|
} |
|
pool->free_head = NULL; |
|
pool->object_size = object_size; |
|
pool->free_count = 0; |
|
pool->allocations = 0; |
|
pool->reuse_count = 0; |
|
return pool; |
|
} |
|
|
|
// Выделить объект из пула или из malloc |
|
void* memory_pool_alloc_impl(struct memory_pool* pool, const char* location) { |
|
if (!pool) { |
|
return NULL; |
|
} |
|
|
|
if (pool->free_head) { |
|
void* obj = pool->free_head; |
|
pool->free_head = *(void**)obj; // Извлекаем next из начала блока |
|
pool->free_count--; |
|
g_total_free--; |
|
pool->reuse_count++; |
|
memset(obj, 0, pool->object_size); // Опционально: очищаем память для безопасности |
|
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "pool_alloc reused: %s, remaining=%zu", location, pool->free_count); |
|
return obj; |
|
} |
|
|
|
pool->allocations++; |
|
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "pool_alloc: %s, total_allocs=%zu", location, pool->allocations); |
|
return u_calloc_impl(1, pool->object_size, location); // Используем calloc для инициализации нулями |
|
} |
|
|
|
// Освободить объект в пул или в free |
|
void memory_pool_free_impl(struct memory_pool* pool, void* obj, const char* location) { |
|
if (!pool || !obj) { |
|
return; |
|
} |
|
|
|
// Если пул не заполнен, сохранить объект для повторного использования |
|
if (pool->free_count < MEMORY_POOL_MAX_FREE) { |
|
*(void**)obj = pool->free_head; // Сохраняем next в начало блока |
|
pool->free_head = obj; |
|
pool->free_count++; |
|
g_total_free++; |
|
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "pool_free returned: %s, free_count=%zu", location, pool->free_count); |
|
return; |
|
} |
|
|
|
// Иначе освободить через free |
|
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "pool_free direct: %s", location); |
|
u_free_impl(obj, location); |
|
} |
|
|
|
// Получить статистику пула |
|
void memory_pool_get_stats(struct memory_pool* pool, size_t* allocations, size_t* reuse_count) { |
|
if (!pool) { |
|
return; |
|
} |
|
if (allocations) { |
|
*allocations = pool->allocations; |
|
} |
|
if (reuse_count) { |
|
*reuse_count = pool->reuse_count; |
|
} |
|
} |
|
|
|
// Очистить пул памяти |
|
void memory_pool_destroy(struct memory_pool* pool) { |
|
if (!pool) { |
|
return; |
|
} |
|
|
|
int cnt=0; |
|
// Освободить все объекты в пуле |
|
void* obj = pool->free_head; |
|
while (obj) { |
|
void* next = *(void**)obj; |
|
g_total_free--; |
|
u_free(obj); |
|
cnt++; |
|
obj = next; |
|
} |
|
|
|
// if (cnt>MEMORY_POOL_MAX_FREE) |
|
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "pool_destroy: allocations=%zu, reuse=%zu, current pool size=%d", pool->allocations, pool->reuse_count, cnt); |
|
|
|
pool->free_head = NULL; |
|
pool->free_count = 0; |
|
u_free(pool); |
|
}
|
|
|