Чтение онлайн

на главную

Жанры

Системное программирование в среде Windows

Харт Джонсон М.

Шрифт:

ic = r2c_msg.destination; /* Конечный потребитель. */

tstatus = q_put(&r2cq_array[ic], &r2c_msg, sizeof(r2c_msg), INFINITE);

if (tstatus != 0) return tstatus;

}

 }

 return 0;

}

DWORD WINAPI consumer(PVOID arg) {

 THARG * carg;

 DWORD tstatus, ithread;

 msg_block_t msg;

 queue_t *pr2cq;

 carg = (THARG *)arg;

 ithread = carg->thread_number;

 carg = (THARG *)arg;

 pr2cq = &r2cq_array[ithread];

 while (carg->work_done < carg->work_goal) {

/*
Получить и отобразить (необязательно — не показано) сообщения. */

tstatus = q_get(pr2cq, &msg, sizeof(msg), INFINITE);

if (tstatus != 0) return tstatus;

carg->work_done++;

 }

 return 0;

}
 

Комментарии по поводу многоступенчатого конвейера

Данная реализация характеризуется некоторыми особенностями, суть которых частично отражена в комментариях, включенных в листинг программы. На эти же особенности обращают ваше внимание и упражнения 10.6, 10.7 и 10.10.

• Значительные возражения вызывает способ, используемый основным потоком для завершения выполнения передающего и принимающего потоков. Лучшим решением было бы использование конечных интервалов ожидания во внутренних циклах передатчика и приемника и прекращение работы после того, как будет установлен соответствующий глобальный флаг. Другой возможный подход заключается в отмене выполнения потоков, как описано далее в этой главе.

• Обратите внимание на существование симметрии между передающим и принимающим потоками. Как и при реализации очереди, это обстоятельство упрощает проектирование, отладку и сопровождение программы.

• Реализация не сбалансирована в смысле согласования скорости генерации сообщений, емкости конвейера и коэффициента блокирования "передатчик/приемник".

• В данной реализации (программа 10.4) для защиты очередей используются мьютексы. Результаты экспериментов с объектами CRITICAL_SECTION не позволили обнаружить сколько-нибудь заметного ускорения работы программы на однопроцессорной системе (см. приложение В). CS-версия программы, ThreeStageCS, находится на Web-сайте. Аналогичным образом вела себя программа и после того, как в ней была использована функции SignalObjectAndWait.

Асинхронные вызовы процедур

Основное возражение, которое можно предъявить к программе ThreeSage.c (программа 10.5) в ее нынешнем виде, касается прекращения выполнения передающего и принимающего потоков с помощью функции TerminateThread. В комментариях, включенных в код, вам предлагается подумать над более элегантным способом завершения выполнения потоков, который обеспечивал бы корректное прекращение работы программы и освобождение ресурсов.

Другой нерешенной проблемой является отсутствие общего метода (не считая использования функции TerminateThread), который обеспечивал бы отправку сигнала определенному потоку или инициировал его выполнение. События могут посылать сигналы одному потоку, ожидающему наступления автоматически сбрасываемого события, или всем потокам, ожидающим наступления вручную сбрасываемого события, но невозможно добиться того, чтобы сигнал был получен определенным потоком.

Используемое до сих пор решение сводилось к тому, что пробуждались все ожидающие потоки, которые самостоятельно определяли, могут ли они теперь продолжить свое выполнение. Иногда привлекается альтернативное решение, суть которого состоит в назначении событий определенным потокам, так что сигнализирующий поток может определять, объект какого события следует перевести в сигнальное состояние одной из функций SetEvent или PulseEvent.

Обе эти проблемы решаются путем использования объектов асинхронного вызова процедур (Asynchronous Procedure Call, АРС). События развиваются в следующей последовательности, причем рабочий или целевой потоки должны управляться главным потоком.

• Главный поток указывает АРС-функцию данной целевого потока путем помещения объекта АРС в очередь АРС данного потока. В очередь могут быть помещены несколько АРС.

• Целевой поток переходит в состояние дежурного ожидания (alertable wait state), обеспечивающее возможность безопасного выполнения потоком АРС. Порядок первых двух шагов безразличен, поэтому о возникновении условий состязательности можно не беспокоиться.

• Указанный поток, находящийся в состоянии ожидания, выполняет все АРС, находящиеся в очереди.

• АРС могут выполнять любые нужные действия, например, освобождать ресурсы или генерировать исключения. Благодаря этому главный поток может инициировать возбуждение исключения в целевом потоке, хотя само исключение не произойдет до тех пор, пока целевой поток не перейдет в состояние дежурного ожидания.

Выполнение АРС является асинхронным в том смысле, что АРС может быть помещен в очередь целевого потока в любой момент, но само выполнение является синхронизированным в том смысле, что это может произойти лишь тогда, когда целевой поток входит в состояние дежурного ожидания.

Состояния дежурного ожидания будут вновь обсуждаться в главе 14, посвященной асинхронному вводу/выводу.

Описания необходимых функций и примеры их использования в другом варианте программы ThreeStage приводятся в следующих разделах. Проект для построения новой версии программы (ThreeStageCancel) и соответствующий исходный код (ThreeStageCancel. с) находятся на Web-сайте книги.

Очередизация асинхронных вызовов процедур

Один поток (главный) помещает АРС в очередь целевого потока с помощью функции QueueUserAPC: 

DWORD QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, DWORD dwData)

hThread — дескриптор целевого потока. dwData — аргумент, который будет передан функции АРС при ее выполнении и может являться кодом завершения или сообщать функции иную информацию.

В основной функции программы ThreeStageCancel.с (сравните с программой 10.5) вызовы TerminateThread заменяются вызовами QueueUserAPC следующим образом:

// TerminateThread(transmitter_th, 0) ; заменить на АРС

// TerminateThread(receiver_th, 0); заменить на АРС

tstatus = QueueUserAPC(ShutDownTransmitter, transmitter_th, 1);

if (tstatus == 0) ReportError(…);

tstatus = QueueUserAPC(ShutDownReceiver, receiver_th, 2);

if (tstatus == 0) ReportError (…);

Функция QueueUserAPC в случае успешного ее завершения возвращает ненулевое значение, иначе — нуль. В то же время, функция GetLastError не возвращает никакого полезного значения, и поэтому при вызове функции ReportError не требуется задавать текст сообщения об ошибке (значением последнего аргумента является FALSE).

Поделиться:
Популярные книги

Лорд Системы 4

Токсик Саша
4. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 4

Кремлевские звезды

Ромов Дмитрий
6. Цеховик
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Кремлевские звезды

Академия

Сай Ярослав
2. Медорфенов
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Академия

Снегурка для опера Морозова

Бигси Анна
4. Опасная работа
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Снегурка для опера Морозова

Дядя самых честных правил 8

Горбов Александр Михайлович
8. Дядя самых честных правил
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Дядя самых честных правил 8

Третий. Том 3

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 3

Законы Рода. Том 2

Flow Ascold
2. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 2

СД. Том 17

Клеванский Кирилл Сергеевич
17. Сердце дракона
Фантастика:
боевая фантастика
6.70
рейтинг книги
СД. Том 17

Назад в СССР 5

Дамиров Рафаэль
5. Курсант
Фантастика:
попаданцы
альтернативная история
6.64
рейтинг книги
Назад в СССР 5

Я же бать, или Как найти мать

Юнина Наталья
Любовные романы:
современные любовные романы
6.44
рейтинг книги
Я же бать, или Как найти мать

Иван Московский. Первые шаги

Ланцов Михаил Алексеевич
1. Иван Московский
Фантастика:
героическая фантастика
альтернативная история
5.67
рейтинг книги
Иван Московский. Первые шаги

Пенсия для морского дьявола

Чиркунов Игорь
1. Первый в касте бездны
Фантастика:
попаданцы
5.29
рейтинг книги
Пенсия для морского дьявола

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Безымянный раб

Зыков Виталий Валерьевич
1. Дорога домой
Фантастика:
фэнтези
9.31
рейтинг книги
Безымянный раб