Применение Windows API - страница 18

Шрифт
Интервал

стр.

Активный Объект сформирован как каркас по имени ActiveObject. Построение производного класса, как предполагается, обеспечивает реализацию для чистых виртуальных методов InitThread, Run и Flush (также как и написание деструктора).

>class ActiveObject {

>public:

> ActiveObject();

> virtual ~ActiveObject() {}

> void Kill();

>protected:

> virtual void InitThread() = 0;

> virtual void Run() = 0; virtual void FlushThread() = 0;

> static DWORD WINAPI ThreadEntry(void *pArg);

> int _isDying;

> Thread _thread;

>};

Конструктор класса ActiveObject инициализирует удерживаемый поток, передавая ему указатель функции, которую предполагается выполнить и указатель "this" на себя. Мы должны отключить предупреждение, сигнализирующее об использовании "this" до полного создания объекта. Мы знаем, что этот объект не будет использоваться раньше положенного, потому что поток создается в неактивном состоянии. Предполагается, сто конструктор производного класса вызывает _thread.Resume() чтобы активизировать поток.

>// The constructor of the derived class

>// should call

>// _thread.Resume ();

>// at the end of construction

>ActiveObject::ActiveObject() : _isDying (0),

>#pragma warning(disable: 4355) // 'this' used before initialized

> _thread(ThreadEntry, this)

>#pragma warning(default: 4355)

>{ }

Метод Kill вызывает виртуальный метод FlushThread — это необходимо для завершения потока из любого состояния ожидания и дает ему возможность запустить _isDying для проверки флажка.

>void ActiveObject::Kill() {

> _isDying++;

> FlushThread();

> // Let's make sure it's gone

> _thread.WaitForDeath();

>}

Мы также имеем каркас для функции ThreadEntry (это — статический метод класса ActiveObject, поэтому мы можем определять соглашение о вызовах, требуемое API). Эта функция выполняется удерживаемым потоком. Параметр, получаемый потоком от системы является тем, который мы передали конструктору объекта потока — это указатель "this" Активного Объекта. API ожидает void-указатель, поэтому мы должны делать явное приведение указателя на ActiveObject. Как только мы овладеваем Активным Объектом, мы вызываем его чистый виртуальный метод InitThread, делать все специфические для реализации приготовления, а затем вызываем основной рабочий метод Run. Реализация метода Run оставлена клиенту каркаса.

>DWORD WINAPI ActiveObject::ThreadEntry(void* pArg) {

> ActiveObject* pActive = (ActiveObject*)pArg;

> pActive->InitThread();

> pActive->Run();

> return 0;

>}

Объект Thread — это тонкая инкапсуляция API. Обратите внимание на флажок CREATE_SUSPENDED, который гарантирует, что нить не начнет выполняться прежде, чем мы не закончим конструирование объекта ActiveObject.

>class Thread {

>public:

> Thread(DWORD(WINAPI* pFun)(void* arg), void* pArg) {

>  _handle = CreateThread(

>   0, // Security attributes

>   0, // Stack size

>   pFun, pArg, CREATE_SUSPENDED, &_tid);

> }

> ~Thread() {

>  CloseHandle(_handle);

> }

> void Resume() {

>  ResumeThread(_handle);

> }

> void WaitForDeath() {

>  WaitForSingleObject(_handle, 2000);

> }

>private:

> HANDLE _handle;

> DWORD _tid; // thread id

>};

Синхронизация — это то, что действительно делает многозадачный режим столь интенсивно используемым. Давайте, начнем со взаимных исключений. Класс Mutex — тонкая инкапсуляция API. Вы внедряете Mutexes (мутации) в ваш Активный Объект, а затем используете их через Блокировки. Блокировка (Lock) — умный объект, который создается на стеке. В результате чего, во время обслуживания, ваш объект защищен от любых других потоков. Класс Lock — одно из приложений методологии Управления ресурсами. Вы должны поместить Lock внутри всех методов вашего Активного Объекта, которые разделяют доступ к данным с другими потоками.

>class Mutex {

> friend class Lock;

>public:

> Mutex() {

>  InitializeCriticalSection(&_critSection);

> }

> ~Mutex() {

>  DeleteCriticalSection(&_critSection);

> }

>private:

> void Acquire() {

>  EnterCriticalSection(&_critSection);

> }

> void Release() {

>  LeaveCriticalSection(&_critSection);

> }

> CRITICAL_SECTION _critSection;

>};


>class Lock {

>public:

> // Acquire the state of the semaphore

> Lock(Mutex& mutex) : _mutex(mutex) {

>  _mutex.Acquire();


стр.

Похожие книги