Files
fxalloc/includes/FXAlloc.h
T

130 lines
8.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
/**
* @file neurox/ccpp/fxalloc/includes/FXAlloc.h
* @author felex67 (admin@felexdev.ru)
* @version 1.0.0 beta
* @brief Публичный интерфейс модуля-аллокатора fxalloc(includes/FXAlloc.h)
*
* @details Language: C11 (ISO/IEC 9899:2011).
* Теоритический маскимальный размер блока `(1 << 32) - 25 = 4 294 967 271 байт`
* Первый вызов `fxalloc()`(без предварительного вызова `fxalloc_init()`) в потоке/процессе крайне медленный
* так как происходит инициализация пула, последующие вызовы будут работать с инициализированным
* пулом памяти.
* Изначально аллокатор работает в следующем режиме:
* `fxalloc → выделение блока через malloc() с добавлением метаданных`,
* `fxfree → анализ метаданных с последующим вызовом free()`. Такое поведение
* помогает сборать статистику для профилирования, которые могут быть получены
* переводом аллокатора в режим анализа(выполняется потоком-наблюдателем).
* При необходимости выделения отдельного пула для потока используйте `fxalloc_init()`,
* в глобальном пуле(НЕ TLS!!!) будет выделен блок памяти для этого потока, что даст возможность
* передачи данных по очередям между потоками без повторных выделений, функция `fxfree()`
* из любого другого потока вернёт блок владельцу без накладных расходов на TLS, только
* атомарная синхронизация.\
* Изменение указателей `fxalloc` и `fxfree` строго запрещено!\
* Без оперделения макроса `_I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_` модуль
* не скомпилируется, возникнет ошибка компиляции, определение макроса = подписание конракта.\
* По завершению работы потока/процесса в системах POSIX вся выделенная память
* освобождается автоматически, в Windows необходимо вызвать `fxalloc_cleanup()`.
* */
#include <stdint.h>
#ifdef _WIN32 // Windows
#include <Windows.h>
#define thread_local __declspec(thread)
#else // Linux
#include <threads.h>
#define thread_local __thread
#endif //_WIN32
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
/**
* @brief Перечисление режимов работы аллокатора
*/
typedef enum eFXAllocProfile {
FXALLOC_SPEED, ///< Максимальная производительность без статистики
FXALLOC_SUMMARY, ///< Поверхностная статистика
FXALLOC_FULL ///< Глубокий анализ расхода памяти
} eFXAllocProfile;
/**
* @brief Структура преднастройки аллокатора задающая градации и количество блоков памяти.
* Массив должен быть отсортирован по возрастанию размера блока
* и заканчиваться элементом с `est_size = 0`
* @var +est_size: size_t - Предполагаемый размер блока
* @var +est_count: size_t - Предполагаемое количество блоков
*/
typedef struct FXGrade {
const size_t est_size; ///< Предполагаемый размер блока
const size_t est_count; ///< Предполагаемое количество блоков
} FXGrade;
/**
* @brief Переключает режимы работы алокатора
* `FXALLOC_SPEED` - Максимальная производительность без статистики
* `FXALLOC_SUMMARY` - Поверхностная статистика
* `FXALLOC_FULL` - Глубокий анализ расхода памяти
* @retval `1` при успешном переключении
* @retval `0` при ошибке(не вероятно)
*/
int fxalloc_profile(eFXAllocProfile Profile);
/**
* @brief Инициализирует локальный пулл памяти исходя из заданных параметров блоков
* @param[in] Grades: const FXGrade* - Указатель на массив градаций
* @param[in] ThreadName: const char* - Наименование потока, используется при профилировании
* в следующем виде: `[thread_id] 'thread_name': blocks: total=1024 used=64...`.
* Если передан `NULL` - выводится только ID потока, т.е.: `[thread_id]: ...`
*/
int fxalloc_init(const FXGrade* Grades, const char* ThreadName);
#ifndef _I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_
/**
* @brief Указатель на функцию выделения памяти
* @note Ни в коем разе не должен изменяться из вызывающего кода!!!
* @param[in] NBytes: size_t - Количество байт
* @retval `!0` - С адресом кратным размеру `sizeof(size_t)`. Указатель выровненный для любого типа данных
* @retval `NULL` - В случае единственно возможной ошибки `ENOMEM` результат сохранён в `errno`
* подробное описание `strerror(errno)`
*/
extern thread_local void (*const fxalloc)(size_t NBytes);
#else
/**
* @brief Указатель на функцию выделения памяти
* @note Ни в коем разе не должен изменяться из вызывающего кода!!!
* @param[in] NBytes: size_t - Количество байт
* @retval !0 - Кратный размеру(sizeof(size_t)) указатель выровненный для любого типа данных
* @retval NULL - В случае единственно возможной ошибки ENOMEM результат сохранён в errno
*/
extern thread_local void (*fxalloc)(size_t NBytes);
#endif
#ifndef _I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_
/**
* @brief Указатель на функцию высвобождения памяти выделенной исключительно fxalloc
* при использовании на любом другом указателе 100% неопределённое поведение
* @note Ни в коем разе не должен изменяться из вызывающего кода!!!
* @param[in] Ptr: void* - Указатель на блок памяти
*/
extern thread_local void (*const fxfree)(void* Ptr);
#else
/**
* @brief Указатель на функцию высвобождения памяти выделенной исключительно fxalloc
* при использовании на любом другом указателе 100% неопределённое поведение
* @note Ни в коем разе не должен изменяться из вызывающего кода!!!
* @param[in] Ptr: void* - Указатель на блок памяти
*/
extern thread_local void (*fxfree)(void* Ptr);
#endif
/**
* @brief Высвобождает ресурсы занятые потоком. Вызывать непосредственно перед выходом
* из потока/процесса, в противном случае - `UB` или `segfault`
*/
void fxalloc_cleanup();
#ifdef __cplusplus
}
#endif //__cplusplus