- •Раздел 2. Механизмы последовательного выполнения программ
- •2.1. Классификация методов замены контекста
- •2.2. Процедуры как синхронные методы замены контекста
- •2.3. Сопрограммы
- •2.4. Примеры реализации сопрограмм в Си, в защищенном режиме процессора и в Win32
- •2.4.1. Пример реализации сопрограмм в Си
- •2.4.2. Пример реализации сопрограмм в защищенном режиме
- •2.4.3. Пример реализации сопрограмм в Win32
- •2.5. Процедуры ос
- •2.6. Прерывания как асинхронный метод замены контекста
- •2.7. Исключения
- •2.7.1. Самая общая характеристика исключений
- •2.7.2 Исключения на низком уровне
- •2.7.3. Исключения в программных средах
- •2.7.4. Обработка исключений в Delphi
- •2.7.4.1. Защита ресурсов
- •2.7.4.2. Обработка исключений
2.4.3. Пример реализации сопрограмм в Win32
В Win32 существует средство, называемое Fiber (нить).
Нити могут быть использованы для достижения следующих целей:
Для переноса приложений UNIX, в которых используется управление потоками, в среду Windows.
Для реализации сопроцедур, посредствам чего приложение переключается между несколькими взаимосвязанными заданиями.
API нитей включает 6 функций:
ConvertThreadToFiber – включение возможности использовать нити и превращение main-потока в главную нить.
CreateFiber - Создание дополнительных нитей.
GetFiberData – получение данных, сформированных при создании нити.
GetCurrentFiber – получение идентификатора активной нити (собственного идентификатора).
SwitchToFiber – переключение на другую нить.
DeleteFiber – удаление нити.
Нити имеют собственные стеки.
Существует два способа управления нитями:
Управление «ведущий-ведомый», когда все нити передают управление главной нити, а та в свою очередь решает, какой из нитей передать управление.
Равноправное управление, когда сама нить определяет, какая из нитей будет выполняться следующей.
Ниже приведен текст примера, использующего нити Win32.
#include <windows.h>
#include <stdio.h>
#define FIBER_COUNT 3 // total number of fibers (including primary)
#define MAIN_FIBER 0 // array index to main fiber
#define FIRST_FIBER 1 // array index to first fiber
#define SECOND_FIBER 2 // array index to second fiber
LPVOID lpFiber[FIBER_COUNT];
//===================================================================
VOID __stdcall FirstFiberFunc(LPVOID lpParameter) {
int i = 0;
while (1) {
printf("FirstFiberFunc; i = %d\n",i);
i++;
if (i > 11) {
break;
}
SwitchToFiber(lpFiber[SECOND_FIBER]);
}
printf("FirstFiberFunc: return to main fiber\n");
SwitchToFiber(lpFiber[MAIN_FIBER]);
}
//===================================================================
VOID __stdcall SecondFiberFunc(LPVOID lpParameter){
int i = 0;
while (1) {
printf("SecondFiberFunc; i = %d\n",i);
i++;
if (i > 10) {
break;
}
SwitchToFiber(lpFiber[FIRST_FIBER]);
}
printf("SecondFiberFunc: return to main fiber\n");
SwitchToFiber(lpFiber[MAIN_FIBER]);
}
//====================================================================
int __cdecl main(int argc,char *argv[]){
lpFiber[MAIN_FIBER] = ConvertThreadToFiber(NULL);
lpFiber[FIRST_FIBER] = CreateFiber(0, FirstFiberFunc, NULL);
lpFiber[SECOND_FIBER] = CreateFiber(0, SecondFiberFunc, NULL);
SwitchToFiber(lpFiber[FIRST_FIBER]);
DeleteFiber(lpFiber[FIRST_FIBER]);
DeleteFiber(lpFiber[SECOND_FIBER]);
printf("main fiber\n");
return 0;
}
//====================================================================
Вопрос (
Этапы создания задач-сопрограмм во всех трех примерах одни и те же. Это:
выделение памяти под стеки (стек для main выделять не надо);
выделение памяти под дескрипторы (в том числе и для main);
необходимым образом выполненная инициализация стеков;
необходимым образом выполнение инициализации дескрипторов;
переход из задачи main в одну из сопрограмм;
переключение сопрограмм по требуемому алгоритму;
возвращение в задачу main.
)Вопрос
