Исправлена ошибка в именовании
This commit is contained in:
+25
-2
@@ -1,4 +1,4 @@
|
||||
# ccpp/fxalloc/DAIRY.md
|
||||
# ccpp/fxalloc/DIARY.md
|
||||
|
||||
# Дисклеймер:
|
||||
* Дневник не является технической документацией.
|
||||
@@ -1077,6 +1077,29 @@ P.S.: Как-то странно, обычно Алиса ругается чт
|
||||
* **CriticalSection** — чуть менее долгий чем предыдущий(имеет ТРД)
|
||||
* **futex** — ещё более продвинутый(Конкорд)
|
||||
* **Абсолютная надёжность** с хитропопны манипуляциями:
|
||||
* **Атомарные операции(Interlocket/build-ins)** — искомая 3-я космическая
|
||||
* **Атомарные операции(Interlocked/build-ins)** — искомая 3-я космическая
|
||||
|
||||
## Синхронизация с точки зрения аллокатора
|
||||
|
||||
Единственно верным решением для синхронизации потоков в аллокаторе являются атомарные операции без мьютексов. Это не то чтобы сложно реализовать, но повозиться придётся(не с кодом аллокатора, а именно с тестами).
|
||||
|
||||
## Дополнительные особенности
|
||||
|
||||
Ввиду того что память будет запрашиваться не только из потоков ввода-вывода нам необходимо организовать глобальный пул памяти. Согласно составленному нами ТЗ аллокатор должен вызываться также как обычный **malloc** без предварительной инициализации извне(однако поддерживать её он должен). Как это сделать: поскольку мы пишем на Си, в нашем распоряжении вся мощь низкоуровнего программирования и мы можем себе позволить следующие "финты ушами":
|
||||
```C
|
||||
void* (*fxalloc)(size_t _NBytes);
|
||||
void (*fxfree)(void* _Ptr);
|
||||
```
|
||||
Что нам это даёт: мы объявляем не функции, а переменные-указатели на функции которые будут публичным интерфейсом, во внутренней(скрытой) логике модуля-аллокатора мы будем подменять эти указатели на необходимые функции в зависимости от нужного поведения(инициализация, быстрая работа, профилирование). Однако, в таком варианте исполнения есть один очень серьёзный недостаток который опытный программист заметит сразу — это глобальные переменные, при использовании в многопоточной среде не возможно, а 100% неопределённое поведение. Как решить эту проблему, просто — объявить все функции модуля как внутрипоточные, в таком случае каждый поток получит свои экземпляры указателей на функцции и свой пул памяти в глобальной области без дополнительных расходов:
|
||||
```C
|
||||
/* Windows С-11 */
|
||||
__declspec(thread) void* (*fxalloc)(size_t _NBytes);
|
||||
__declspec(thread) void (*fxfree)(void* _Ptr);
|
||||
/* POSIX С-11 */
|
||||
thread_local void* (*fxalloc)(size_t _NBytes);
|
||||
thread_local void (*fxfree)(void* _Ptr);
|
||||
```
|
||||
|
||||
|
||||
|
||||
Единственным узким местом остаётся переключение режимов, как это сделать расмотрим далее
|
||||
Reference in New Issue
Block a user