Files
fxalloc/includes/FXAlloc.h
T

111 lines
6.5 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).
* Изначально аллокатор работает в следующем режиме:
* `fxalloc → выделение блока через malloc() с добавлением метаданных`,
* `fxfree → анализ метаданных с последующим вызовом free()`. Такое поведение
* помогает сборать статистику для профилирования, которые могут быть получены
* переводом аллокатора в режим анализа(выполняется потоком-наблюдателем).
* При необходимости выделения отдельного пула для потока используйте `fxalloc_init()`,
* в глобальном пуле(НЕ TLS!!!) будет выделен блок памяти для этого потока, что даст возможность
* передачи данных по очередям между потоками без повторных выделений, функция `fxfree()`
* из любого другого потока вернёт блок владельцу без накладных расходов на TLS, только
* атомарная синхронизация.\
* Изменение указателей `fxalloc` и `fxfree` строго запрещено! Без оперделения макроса
* `_I_UNDERSTAND_THE_RISKS_AND_ASSUME_RESPONSIBILITY_` возникнет ошибка компиляции.\
* По завершению работы потока/процесса в системах POSIX вся выделенная память
* освобождается автоматически, в Windows необходимо вызвать `fxalloc_cleanup()`.
* */
#include <stdint.h>
#include <threads.h>
#ifdef _WIN32 // Windows
#define thread_local __declspec(thread)
#else // Linux
#define thread_local __thread
#endif //_WIN32
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
/**
* @brief Перечисление режимов работы аллокатора
*/
typedef enum {
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 !0 при успешном переключении
* @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);
/**
* @brief Указатель на функцию выделения памяти
* @note Ни в коем разе не должен изменяться из вызывающего кода!!!
* @param[in] NBytes: size_t - Количество байт
* @retval !0 - Кратный размеру(sizeof(size_t)) указатель выровненный для любого типа данных
* @retval NULL - В случае единственно возможной ошибки ENOMEM результат сохранён в errno
*/
#ifndef _I_UNDERSTAND_THE_RISKS_AND_ASSUME_RESPONSIBILITY_
extern thread_local void (*const fxalloc)(size_t NBytes);
#else
extern thread_local void (*fxalloc)(size_t NBytes);
#endif
/**
* @brief Указатель на функцию высвобождения памяти выделенной исключительно fxalloc
* при использовании на любом другом указателе 100% неопределённое поведение
* @note Ни в коем разе не должен изменяться из вызывающего кода!!!
* @param[in] _Ptr: void* - Указатель на блок памяти
*/
#ifndef _I_UNDERSTAND_THE_RISKS_AND_ASSUME_RESPONSIBILITY_
extern thread_local void (*const fxfree)(void* Ptr);
#else
extern thread_local void (*fxfree)(void* Ptr);
#endif
/**
* @brief Высвобождает ресурсы занятые потоком Вызывать непосредственно перед выходом,
* в противном случае UB или segfault
*/
void fxalloc_cleanup();
#ifdef __cplusplus
}
#endif //__cplusplus