#pragma once /** * @file fxalloc/headers/_FXAlloc.h * @author felex67 (admin@felexdev.ru) * @version 1.0.0 dev-in-progress * * @brief Внутренний заголовочный файл модуля FXAlloc */ #include "FXAlloc.h" #ifdef __cplusplus extern "C" { #endif #include #include typedef struct FXMemoryBlock FXMemoryBlock; typedef struct FXGradePool FXGradePool; #if defined(_I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_) && defined(__FXALLOC_TURBO) /*===================================================================================================* * !!! Опасный режим !!! * * Сугубо для отпрофилированных серверов. Режим глубокого профилирования не доступен. * *===================================================================================================*/ #pragma pack(push, 16) /** * @brief Метаданные отдельного блока памяти * */ struct FXMemoryBlock { FXMemoryBlock* next; ///< Следующий в стэке свободных FXGradePool* pool; ///< Указатель на конкретный грейд хозяина uint8_t data[]; ///< Пользовательские данные }; #pragma pack(pop) #pragma pack(push, 16) /** * @brief Элемент пула потока выделяемый для градации * */ struct FXGradePool { _Atomic FXMemoryBlock* lifo; ///< Стэк свободных блоков _Atomic uint32_t ntotal; ///< Блоков всего _Atomic int32_t nfree; ///< Блоков свободно }; #pragma pack(pop) #else /*===================================================================================================* * Режим работы в формате профилировщика с возможностью расширенной статистики * *===================================================================================================*/ #pragma pack(push, 16) /** * @brief Метаданные отдельного блока памяти * */ struct FXMemoryBlock { FXMemoryBlock* next; ///< Следующий в стэке свободных FXGradePool* pool; ///< Указатель на конкретный грейд хозяина FXMemoryBlock* list; ///< Следующий в списке алоцированных uint32_t used; ///< Использовано байт uint32_t padding; ///< Это ненужные байты, во всяком случае - пока uint8_t data[]; ///< Пользовательские данные }; #pragma pack(pop) #pragma pack(push, 8) /** * @brief Элемент пула потока выделяемый для градации * */ struct FXGradePool { _Atomic FXMemoryBlock* lifo;///< Стэк свободных блоков FXMemoryBlock* list; ///< Список аллоцированных блоков FXMemoryBlock* prealloced; ///< Преаллоцированные блоки _Atomic uint32_t ntotal; ///< Блоков всего _Atomic int32_t nbusy; ///< Блоков занято uint32_t nprealloc; ///< Блоков преаллоцировано uint32_t nalloc; ///< Блоков алоцировано через `malloc` uint32_t vref; }; #pragma pack(pop) #endif //__FXALLOC_TURBO #pragma pack(push, 8) /** * @brief Пул памяти потока * */ typedef struct FXThreadPool { void* (**curr_alloc)(size_t NBytes);///< Указатель на указатель на функцию аллокации действующую в данном потоке(для профилирования) void (**curr_free)(void* Ptr); ///< Указатель на указатель на функцию освобождения действующую в данном потоке(для профилирования) eXFAllocSearchType* search_type; ///< Указатель на переменную хранящую информацию о типе функций аллокации для данного потока(нужна при переключении режимов работы) uint32_t isActive; ///< Показатель активности потока(для профилировщика, он же - сборщик мусора) uint32_t ngrades; ///< Количество градаций FXGradePool* grades[]; ///< Массив указателей на грейды, заканчивается NULL } FXThreadPool; #pragma pack(pop) /** * @brief Глобальный пул памяти * */ typedef struct FXGlobalMemoryPool { FXThreadPool** pools; ///< Массив указателей на пулы потоков, заканчивается NULL fxsync_t mutex; ///< Мьютекс для синхронизации при инициализации для локального пула } FXGlobalMemoryPool; /*=====================================================================================================* * Работа аллокатора в режиме проксирования. Эти функции работают только если не определён макрос * *=====================================================================================================*/ /** * @brief Макрос условной компиляции квалификаторов типа указателя для `fxalloc` и `fxfree` * В случае если не определён данный блок кода компилируется и все вызовы происзодят через * прокси функцию * */ #ifndef _I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_ /** @brief Указатель на активную функцию аллокации */ extern TLS void* (*thread_alloc)(size_t NBytes); /** @brief Указатель на активную функцию аллокации */ extern TLS void (*thread_free)(void* Ptr); /** * @brief Прокси-функция аллокации * * @param NBytes Количество байт * * @return void* * @retval !NULL Указатель на область памяти выровненный по sizeof(void*) * @retval NULL ошибка выделения памяти */ void* fxalloc_proxy_alloc(size_t NBytes); /** * @brief Прокси-функция высвобождения * * @param Ptr указатель на блок выделенный пользователю */ void fxalloc_proxy_free(void* Ptr); #endif //_I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_ /*=====================================================================================================* * Локальные потоковые переменные * *=====================================================================================================*/ /** * @brief Указатель на пул данного потока * Изначально равен NULL, инициализируется при первом вызове `fxalloc` или `fxalloc_init` */ extern TLS FXThreadPool* thread_pool; /** * @brief Переменная хранящая тип поиска для функций выеления памяти в данном потоке * При первом вызове `fxalloc` без предварительного вызова `fxalloc_init` устанавливается в `FXSEARCH_SHIFTED`, * в противном случае определяется функцией `fxalloc_init` */ extern TLS eXFAllocSearchType search_type; /** * @brief Текущий профиль потока * FXALLOC_SPEED | FXALLOC_SUMMARY | FXALLOC_FULL */ extern TLS eFXAllocProfile thread_profile; /*=====================================================================================================* * Инициализаторы * *=====================================================================================================*/ /** * @brief Функция для инициализации грейдов по-умолчанию * * @param NBytes * @return void* */ void* fxalloc_ungraded_alloc_init(size_t NBytes); /*=====================================================================================================* * Функции выделения памяти * *=====================================================================================================*/ /** @brief Выделение блока. Режим: скорость. Алгоритм поиска: сдвиг битов размера. */ void* fxalloc_shifted_speed(size_t NBytes); /** @brief Выделение блока. Режим: поверхностное профилирование. Алгоритм поиска: сдвиг битов размера. */ void* fxalloc_shifted_summary(size_t NBytes); #ifndef __FXALLOC_TURBO // Обычный режим /** @brief Выделение блока. Режим: глубокое профилирование. Алгоритм поиска: сдвиг битов размера. */ void* fxalloc_shifted_full(size_t NBytes); #endif //__FXALLOC_TURBO /** @brief Выделение блока. Режим: скорость. Алгоритм поиска: бинарный поиск. */ void* fxalloc_binary_speed(size_t NBytes); /** @brief Выделение блока. Режим: поверхностное профилирование. Алгоритм поиска: бинарный поиск. */ void* fxalloc_binary_summary(size_t NBytes); #ifndef __FXALLOC_TURBO // Обычный режим /** @brief Выделение блока. Режим: глубокое профилирование. Алгоритм поиска: бинарный поиск. */ void* fxalloc_binary_full(size_t NBytes); #endif //__FXALLOC_TURBO /** @brief Выделение блока. Режим: скорость. Алгоритм поиска: линейный поиск. */ void* fxalloc_linear_speed(size_t NBytes); /** @brief Выделение блока. Режим: поверхностное профилирование. Алгоритм поиска: линейный поиск. */ void* fxalloc_linear_summary(size_t NBytes); #ifndef __FXALLOC_TURBO // Обычный режим /** @brief Выделение блока. Режим: глубокое профилирование. Алгоритм поиска: линейный поиск. */ void* fxalloc_linear_full(size_t NBytes); #endif //__FXALLOC_TURBO /*=====================================================================================================* * Функции освобождения памяти(возврат в пул) * *=====================================================================================================*/ /** @brief Возврат блока в пул. Режим: скорость */ void* fxfree_speed(void* Ptr); /** @brief Возврат блока в пул. Режим: поверхностное профилирование */ void* fxfree_summary(void* Ptr); /** @brief Возврат блока в пул. Режим: глубокое профилирование */ void* fxfree_full(void* Ptr); #ifdef __cplusplus } #endif