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.
4.6 KiB
4.6 KiB
memory_pool (Object Pool Allocator)
1. Назначение
Быстрый аллокатор объектов фиксированного размера. Вместо постоянных malloc/free хранит до 64 освобождённых объектов в linked list для повторного использования. Применяется для hot-path объектов, которые часто создаются и уничтожаются: пакеты, фрагменты, ACK-пакеты, структуры маршрутизации, TCP-сегменты lwIP и т.д.
Встроенная защита:
- Buffer overflow — канарейка
0xDEADBEAFпосле пользовательских данных проверяется при освобождении. При повреждении — бесконечный цикл (hang) для отладки. - Double free — однобайтный счётчик в метаданных; повторное освобождение детектируется и вызывает hang.
- Вся диагностика пишется через
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, ...).
Не потокобезопасен — каждый пул используется из одного потока (обычно в рамках одного u_async event loop).
2. Как пользоваться
#include "memory_pool.h"
// 1. Создать пул (обычно в init-функции инстанса):
struct memory_pool* pkt_pool = memory_pool_init(sizeof(struct ETCP_DGRAM), "pkt_pool");
// 2. Выделить объект (если есть свободный — вернёт из пула, иначе u_calloc):
struct ETCP_DGRAM* dgram = memory_pool_alloc(pkt_pool);
// 3. Освободить объект (возвращается в пул, если там меньше 64 блоков):
memory_pool_free(pkt_pool, dgram);
// 4. Получить статистику:
size_t allocs, reuse;
memory_pool_get_stats(pkt_pool, &allocs, &reuse);
// reuse много → эффективно; reuse мало → пул слишком мал для нагрузки
// 5. Проверить, в пуле ли объект (0 — не в пуле, 1 — в пуле):
if (memory_pool_is_freed(pkt_pool, obj)) { /* уже освобождён */ }
// 6. Уничтожить пул (при shutdown):
memory_pool_destroy(pkt_pool);
// реально освобождает все кэшированные блоки через u_free() и сам пул.
Важно:
- Если объекты пула используются как элементы
ll_queue, вobject_sizeнужно закладыватьsizeof(struct ll_entry). Например:memory_pool_init(sizeof(struct ll_entry) + sizeof(struct dummynet_pkt), "pkt_pool"). memory_pool_allocобнуляет объект перед возвратом (защита от утечки старых данных).- При заполнении пула (64 свободных блока) лишние
memory_pool_freeреально вызываютu_free— блок не кэшируется. memory_pool_destroyпроходит по всем свободным блокам и вызываетu_freeдля каждого, затем освобождает самstruct memory_pool.
3. API
| Функция/макрос | Описание |
|---|---|
memory_pool_init(object_size, name) |
Создаёт пул для объектов заданного размера. name — для диагностики. |
memory_pool_alloc(pool) |
Выделяет объект: из кэша (если есть) или через u_calloc. Обнуляет перед возвратом. |
memory_pool_free(pool, obj) |
Возвращает объект в пул (до 64) или вызывает u_free. Проверяет canary и double-free. |
memory_pool_destroy(pool) |
Уничтожает пул: освобождает все кэшированные блоки и сам пул. |
memory_pool_get_stats(pool, &allocs, &reuse) |
Статистика: общее число аллокаций и число повторных использований из кэша. |
memory_pool_get_total_free_blocks() |
Глобальный счётчик свободных блоков во всех пулах (для диагностики). |
memory_pool_is_freed(pool, obj) |
Проверяет, находится ли объект в свободном списке пула (уже освобождён). |