- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Системное программирование в среде Windows - Джонсон Харт
Шрифт:
Интервал:
Закладка:
Однако в случае Windows NT 5.x (XP, 2000 и Server 2003) и даже Windows NT 4.0 мы можем использовать функцию SignalObjectAndWait — важный элемент усовершенствования, который избавляет от необходимости применения конечных интервалов ожидания и объединяет освобождение мьютекса и ожидание события. При этом кроме явного упрощения программы, производительность в общем случае повышается, что объясняется устранением системного вызова и отсутствием необходимости в настройке длительности интервала ожидания.
DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
Эта функция, при вызове которой используются дескрипторы, указывающие соответственно на мьютекс и событие, упрощает цикл потребителя. Интервал ожидания здесь отсутствует, поскольку вызывающий поток переходит к ожиданию второго дескриптора сразу же после того, как первый дескриптор переходит в сигнальное состояние (что в данном случае означает освобождение мьютекса). Перевод объекта в сигнальное состояние и переход к ожиданию осуществляются атомарным образом, то есть за одну операцию, так что никакой другой поток не может сигнализировать о наступлении события в течение промежутка времени между освобождением мьютекса вызывающим потоком и ожидания потоком события, на которое указывает второй дескриптор. Тогда упрощенный цикл потребителя приобретает следующий вид:
while (!cvp(&State)) {
SignalObjectAndWait(State.Guard, State.CvpSet, INFINITE, FALSE);
WaitForSingleObject (State.Guard, INFINITE);
}
Значением последнего аргумента этой функции, bAlertable, в данном случае является FALSE, однако в последующих разделах, посвященных рассмотрению АРС, он будет полагаться равным TRUE.
Вообще говоря, оба дескриптора могут указывать на любые подходящие объекты синхронизации. В то же время, использовать объект CRITICAL_SECTION в качестве объекта, сигнальное состояние которого отслеживается, нельзя, поскольку допустимыми являются только объекты ядра.
Функция SignalObjectAndWait применяется во всех примерах программ, представленных как в книге, так и на Web-сайте, хотя на Web-сайте находятся и другие варианты решений, о которых будет говориться в тексте. Если программа должна выполняться под управлением Windows 9x, то следует заменить эту функцию парой функций "сигнал/ожидание", как в первоначально приведенном фрагменте кода, и обязательно использовать конечный интервал ожидания.
В разделе, посвященном АРС, представлены различные методы отправки сигналов ожидающим потокам, обеспечивающие получение сигналов только определенными потоками, тогда как в случае событий простых способов, позволяющих контролировать, каким потокам направляются сигналы, не существует.
Пример: объект порогового барьера
Предположим, вам необходимо, чтобы рабочие потоки оставались в состоянии ожидания и не выполнялись до тех пор, пока количество таких потоков не станет достаточным для образования рабочей группы, способной выполнить нужную работу. Как только количество потоков достигает порогового значения, все ожидающие рабочие потоки начинают выполняться, а появляющиеся впоследствии дополнительные рабочие потоки будут выполняться без ожидания. Эту задачу можно решить путем создания сложного объекта порогового барьера (threshold barrier compound object).
В программах 10.1 и 10.2 представлена реализация трех функций, поддерживающих сложный объект барьера. Две из этих функций, CreateThresholdBarrier и CloseThresholdBarrier, управляют переменными THB_HANDLE, аналогичными дескрипторам, которые на протяжении всего времени применялись нами вместе с объектами ядра. Пороговое количество потоков является параметром функции CreateThresholdBarrier.
Программа 10.1 представляет соответствующую часть заголовочного файла, SynchObj.h, тогда как программа 10.2 — реализацию трех упомянутых функций. Обратите внимание, что объект барьера содержит мьютекс, событие, счетчик и пороговое значение. Предикат переменной условия документирован в заголовочном файле, а именно, событие должно устанавливаться только тогда, когда значение счетчика достигает или становится больше порогового значения.
Программа 10.1. SynchObj.h: часть 1 — объявления объекта порогового барьера/* Глава 10. Сложные объекты синхронизации. */
#define CV_TIMEOUT 50 /* Настраиваемый параметр для модели CV. */
/* ОБЪЕКТ ПОРОГОВОГО БАРЬЕРА — ОПРЕДЕЛЕНИЕ ТИПА И ПРОТОТИПЫ ФУНКЦИЙ. */
typedef struct THRESHOLD_BARRIER_TAG { /* Пороговый барьер. */
HANDLE b_guard; /* Мьютекс для объекта. */
HANDLE b_broadcast; /* Вручную сбрасываемое событие: b_count >= b_threshold.*/
volatile DWORD b_destroyed; /* Установить после закрытия. */
volatile DWORD b_count; /* Количество потоков до достижения барьера. */
volatile DWORD b_threshold; /* Пороговый барьер. */
} THRESHOLD_BARRIER, *THB_HANDLE;
/* Коды ошибок. */
#define SYNCH_OBJ_NOMEM 1 /* Невозможно выделить ресурсы. */
#define SYNCH_OBJ_BUSY 2 /* Объект используется и не может быть закрыт. */
#define SYNCH_OBJ_INVALID 3 /* Объект более не является действительным. */
DWORD CreateThresholdBarrier(THB_HANDLE *, DWORD /* Порог. */);
DWORD WaitThresholdBarrier(THB_HANDLE);
DWORD CloseThresholdBarrier(THB_HANDLE);
Рассмотрим теперь предложенную в программе 10.2 реализацию трех функций. На Web-сайте книги находится тестовая программа testTHB. Обратите внимание на уже знакомый вам цикл проверки переменной условия в функции ожидания WaitThresholdBarrier. Кроме того, эта функция не только ожидает наступления события, но и переводит объект события в сигнальное состояние с помощью функции PulseEvent. Предыдущее обсуждение модели "производитель/потребитель" предполагало использование отдельных функций потоков.
Наконец, в данном случае предикат переменной условия обладает последействием. Как только условие выполнилось, оно будет выполняться и в дальнейшем, что исключает возможность перевода объекта события в сигнальное состояние более одного раза.
Программа 10.2. ThbObject.с: реализация объекта порогового барьера/* Глава 10. Программа 10.2. */
/* Библиотека сложных объектов синхронизации на основе порогового барьера.*/
#include "EvryThng.h"
#include "synchobj.h"
/**********************************/
/* ОБЪЕКТЫ ПОРОГОВОГО БАРЬЕРА */
/**********************************/
DWORD CreateThresholdBarrier(THB_HANDLE *pthb, DWORD b_value) {
THB_HANDLE hthb;
/* Инициализация объекта барьера. Вариант программы с полной проверкой ошибок находится на Web-сайте. */
hthb = malloc(sizeof(THRESHOLD_BARRIER));
hthb->b_guard = CreateMutex(NULL, FALSE, NULL);
hthb->b_broadcast = CreateEvent(NULL, FALSE /* Автоматически сбрасываемое событие. */, FALSE, NULL);
hthb->b_threshold = b_value;
hthb->b_count = 0;
hthb->b_destroyed = 0;
*pthb = hthb;
return 0;
}
DWORD WaitThresholdBarrier(THB_HANDLE thb) {
/* Ожидать, пока заданное количество потоков не достигнет порога, а затем установить событие. */
if (thb->b_destroyed == 1) return SYNCH_OBJ_INVALID;
WaitForSingleObject(thb->b_guard, INFINITE);
thb->b_count++; /* Появился новый поток. */
while (thb->b_count < thb->b_threshold) {
SignalObjectAndWait(thb->b_guard, thb->b_broadcast, INFINITE, FALSE);
WaitForSingleObject(thb->b_guard, INFINITE);
}
PulseEvent(thb->b_broadcast) ;
/* Широковещательная модель CV, освобождение всех ожидающих потоков. */
ReleaseMutex(thb->b_guard);
return 0;
}
DWORD CloseThresholdBarrier(THB_HANDLE thb) {
/* Уничтожить мьютекс и событие объекта барьера. */
/* Убедиться в отсутствии потоков, ожидающих объект. */
if (thb->b_destroyed == 1) return SYNCH_OBJ_INVALID;
WaitForSingleObject(thb->b_guard, INFINITE);
if (thb->b_count < thb->b_threshold) {
ReleaseMutex(thb->b_guard);
return SYNCH_OBJ_BUSY;
}
ReleaseMutex(thb->b_guard);
CloseHandle(thb->b_guard);
CloseHandle(thb->b_broadcast);
free(thb);
return 0;
}
Комментарии по поводу реализации объекта порогового барьера
Возможности реализованного выше объекта порогового барьера в интересах простоты были намеренно ограничены. Вообще говоря, было бы желательно эмулировать объекты Windows следующим образом:
• Разрешив объектам иметь атрибуты защиты (глава 15).
• Разрешив присвоение имен объектам.
• Допуская наличие у одного объекта нескольких "дескрипторов" и не уничтожая их до тех пор, пока счетчик ссылок не станет равным 0.
• Разрешив совместное использование объекта несколькими процессами.
На Web-сайте доступна полная реализация одного из таких объектов — сложного (multiple-wait) семафора, допускающего изменение счетчика семафора сразу на несколько единиц, которая использует методы, применимые по отношению к любому из объектов, рассматриваемых в данной главе.