Windows для профессионалов


Создание инверсных семафоров и типов данных, безопасных в многопоточной среде - часть 2


Очевидно, что самый простой способ обезопасить какой-то ресурс от повреждения в многопоточной среде, — защитить его с помощью критической секции. В С++ это можно сделать без особого труда. Достаточно создать C++ класс, который содержит защищаемую переменную и структуру CRITICAL_SECTION. В конструкторе Вы вызываете lnitializeCriticalSection, а в деструкторе — DeleteCritical Section. Затем для любой переменной-члена Вы вызываете EnterCriticalSection, что-то делаете с этой переменной и вызываете LeaveCriticalSection. Если Вы именно так реализуете С++-класс, то писать безопасный код, обращающийся к какой-либо структуре данных, будет несложно. Этот принцип положен мной в основу всех С++-классов, о которых я буду рассказывать в данном разделе. (Конечно, вместо критических секций я мог бы использовать оптекс, рассмотренный в предыдущем разделе.)

Первый класс, CResGuard, охраняет доступ к ресурсу. Он содержит два элемента данных: CRITICAL_SECTION и LONG. Последний используется для слежения за тем, сколько раз поток, владеющий ресурсом, входил в критическую секцию. Эта информация полезна при отладке. Конструктор и деструктор объекта CResGuard вызывают сответственно InitializeCriticalSeclion и DeleteCriticalSection. Поскольку создать объект может лишь единственный поток, конструктор и деструктор какого-либо С++-объекта не обязательно должен быть реентерабельным. Функция-член IsGuarded просто сообщает, была ли хоть раз вызвана EnterCriticalSection для данного объекта. Как я уже говорил, все это предназначено для отладки. Включение CRITICAL_SECTION в C++ объект гарантирует корректность инициализации и удаления критической секции.

Класс CResGuard также включает открытый вложенный С++-класс CGuard. Объект CGuard содержит ссылку на объект CResGuard и предусматривает лишь конструктор и деструктор. Конструктор обращается к функции-члену Guard класса CResGuard, вызывающей EnterCriticalSection, а деструктор — к функции-члену Unguard того же класса, вызывающей LeaveCriticalSection.


Начало  Назад  Вперед