// memory_pool.c #include #include #include #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); }