| Receiver |
11.02.2025 17:25 |
Привет! Поговорим сегодня о волокнах (fibers) в Windows. Да что вы знаете о волокнах? Кто-нибудь вообще о них слышал? Оказывается слышал. Поэтому начнём обо всём по порядку.
Что из себя представляет волокно? Вырезка из MSDN:
Цитата:
Волокно — это единица выполнения, которую приложение должно запланировать вручную. Волокна выполняются в контексте потоков, которые планируют их. Каждый поток может запланировать несколько волокон. Как правило, волокна не предоставляют преимуществ по сравнению с хорошо спроектированными многопоточных приложений. Однако использование волокон может упростить перенос приложений, предназначенных для планирования собственных потоков.
|
Если говорить на языке фактов, то волокно это управляемый поток. Механизмом работы волокна не отличается от потока. Они не выигрывают по производительности, но зато дают одно важное преимущество пользователю — возможность управления. При этом сами волокна подчиняются потокам, ведь по время их работы Windows продолжает планировать потоки. При переключении с потока выполняющего Fiber на другой его выполнение так же будет приостановлено и продолжиться лишь при обратном переключении.
Как работать с волокном? Первое что мы должны сделать так это конвертировать поток в волокно:
C++:
Код:
// Конвертирует текущий поток в волокно
// Возвращает очень важное значение LPVOID - адрес созданного волокна
// Его нужно хранить для последующих переключений
LPVOID
ConvertThreadToFiber
(
[
in
,
optional
]
LPVOID lpParameter
)
;
// Этой функцией можно получить данные переданные
// волокну в lpParameter, если такие есть
PVOID
GetFiberData
(
)
;
После нам нужно будет создать второе волокно. Создавать волокна мы можем только из волокон, поэтому мы конвертировали поток.
C++:
Код:
// Создаёт новое волокно из уже существующего
// Так же возвращает адрес волокна требующий сохранения
LPVOID
CreateFiber
(
[
in
]
SIZE_T dwStackSize
,
// рамзер стека (можно ставить 0)
[
in
]
LPFIBER_START_ROUTINE lpStartAddress
,
// вызываемая функция
[
in
,
optional
]
LPVOID lpParameter
)
;
// lpParameter точно так же можно получить внутри волокна через GetFiberData
Теперь уже можно заниматься их переключением и делается это очень просто:
C++:
Код:
// Переключает текущее волокно
void
SwitchToFiber
(
[
in
]
LPVOID lpFiber
// адрес волокна на которое нужно переключиться
)
;
Помимо прочего мы можем получить адрес текущего волокна:
C++:
Код:
// Возвращает адрес текущего волокна
PVOID
GetCurrentFiber
(
)
;
Это может пригодиться наверное лишь для проверок, чтобы не допустить рекурсии.
Как волокна хранят данные?
Волокнам точно так же как и потокам нужно хранить принадлежащие им статические данные. Поэтому для этого используется абсолютно идентичный потокам механизм, за исключением изменения одной буквы в аббревиатуре — FLS (Fiber Local Storage). Текущий FLS переключается как при изменении самого волокна, так и управляющего им потока. Управлять этой структурой можно с помощью следующих функций:
C++:
Код:
// Если указан FLS Callback, то вызывается при: удалении волокна, выходе потока, удалении FLS
PFLS_CALLBACK_FUNCTION PflsCallbackFunction
;
void
PflsCallbackFunction
(
[
in
]
PVOID lpFlsData
)
// Создаёт FLS возвращаего его индекс.
DWORD
FlsAlloc
(
[
in
]
PFLS_CALLBACK_FUNCTION lpCallback
)
;
// Возвращает значение по индексу FLS
PVOID
FlsGetValue
(
[
in
]
DWORD dwFlsIndex
)
;
// Устанавливает значение по индексу FLS
BOOL
FlsSetValue
(
[
in
]
DWORD dwFlsIndex
,
[
in
,
optional
]
PVOID lpFlsData
)
;
// Удаляет FLS
BOOL
FlsFree
(
[
in
]
DWORD dwFlsIndex
)
;
И зачем в итоге это всё нужно? С помощью этой дичи мы можем очень легко склепать самопальный менеджер короутин позволяющий вручную управлять выполнением программы и при этом не бояться гонки данных, но только при однопоточной работе приложения! Я уже занимался подобным 22-м году, так что можете ознакомиться: https://www.blast.hk/threads/118982/. Только скажу что на практике это бесполезно, потому что никакого выигрыша по времени не даёт, к тому же сам Microsoft говорит что волокна может лишь упростить перенос приложений. Поэтому всем заинтересованным в короутинах порекомендовал бы использовать asio.
|