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.
 
 
 
 
 
 

114 lines
3.5 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;
static size_t g_total_allocated = 0;
size_t memory_pool_get_total_free_blocks(void) {
return g_total_free;
}
size_t memory_pool_get_total_allocated(void) {
return g_total_allocated;
}
// Инициализировать пул памяти
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++;
g_total_allocated++;
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--;
g_total_allocated--;
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);
}