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


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


Такая схема упрощает манипуляции с CRITICAL_SECTION. Вот небольшой фрагмент кода, иллюстрирующий применение этих классов:

struct SomeDataStruct
{
...
} g_SomeSharedData;

// Создаем объект CResGuard, защищающий g_SomeSharedData.
// Примечание: Конструктор инициализирует критическую секцию, а деструктор удаляет ее.

CResGuard g_rgSomeSharedData;

void AFunction()
{

// эта функция работает с разделяемой структурой данных

// защищаем ресурс от одновременного доступа со стороны нескольких потоков
CResGuard::CGuard gDummy(g_rgSomeSharedData);
// входим в критическую секцию

// работаем c ресурсом g_SomeSharedData

...

}
// Примечание: LeaveCriticalSection вызывается, когда gDummy
// выходит за пределы области видимости

Следующий С++-класс, CInterlockedType, содержит все, что нужно для создания объекта данных, безопасного в многопоточной среде. Я сделал CInterlockediype классом шаблона, чтобы его можно было применять для любых типов данных. Поэтому Вы можете использовать его, например, с целочисленной переменной, строкой или произвольной структурой данных.

Каждый экземпляр объекта CInterlockedType содержит два элемента данных. Первый - это экземпляр шаблонного типа данных, который Вы хотите сделать безопасным в многопоточной среде. Он является закрытым, и им можно манипулировать только через функции-члены класса CInterlockedType. Второй элемент данных представляет собой экземпляр объекта CResGuard, так чго класс, производный от CInterlockedType, может легко защитить свои данные.

Предполагается, что Вы всегда будете создавать свой класс, используя класс CInterlockedType как базовый. Ранее я уже говорил, что класс CInterlockedType предоставляет все необходимое для создания объекта, безопасного в многопоточной среде, но производный класс должен сам позаботиться о корректном использовании элементов CInterlockedType.

Класс CInterlockedType содержит всего четыре открытые функции - конструктор, инициализирующий объект данных, и конструктор, не инициализирующий этот объект, а также виртуальный деструктор, который ничего не делает, и оператор приведения типа (cast operator).


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