Распределенная обработка данных

Контрольная работа - Компьютеры, программирование

Другие контрольные работы по предмету Компьютеры, программирование

аз, когда Вы копируете указатель на интерфейс, надо увеличить его счетчик ссылок. В приведенном далее фрагменте кода делается еще одна ссылка на интерфейс IX. В общем случае необходимо увеличивать счетчик ссылок всякий раз, когда создается копия указателя на интерфейс, о чем говорит приведенное выше правило 3.

 

// Создать компонент

IUnknown* pIUnknown = CreateInstance();

IX* pIX = NULL;

HRESULT hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);

pIUnknown->Release();

if (SUCCEEDED(hr))

{

pIX->Fx(); // Использовать интерфейс IX

IX* pIX2 = pIX; // Создать копию pIX

pIX2->AddRef(); // Увеличить счетчик ссылок

pIX2->Fx(); // Что-то делать при помощи pIX2

pIX2->Release(); // Завершить работу с pIX2

pIX->Release(); // Завершить работу с pIX

}

 

Клиент сообщает компоненту о своем желании использовать интерфейс, когда вызывается

QueryInterface. QueryInterface вызывает AddRef для запрашиваемого интерфейса. Когда клиент заканчивает работу с интерфейсом, он вызывает для этого интерфейса Release. Компонент остается в памяти, ожидая, пока счетчик ссылок не станет равен 0. Когда счетчик становится нулем, компонент сам себя удаляет.

 

Текст программы:

 

#include "stdafx.h"

#include "iostream.h"

#include "objbase.h"

#include "conio.h"

 

void trace(const char* msg) { cout << msg << endl; }

 

// Предварительные описания GUID

extern const IID IID_IX;

extern const IID IID_IY;

extern const IID IID_IZ;

 

// Интерфейсы

interface IX : IUnknown

{

virtual void __stdcall Fx() = 0;

};

interface IY : IUnknown

{

virtual void __stdcall Fy() = 0;

};

interface IZ : IUnknown

{

virtual void __stdcall Fz() = 0;

};

 

// Компонент

class CA : public IX, public IY

{

// Реализация IUnknown

virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);

virtual ULONG __stdcall AddRef();

virtual ULONG __stdcall Release();

 

// Реализация интерфейса IX

virtual void __stdcall Fx() { cout << "Fx" << endl; }

 

// Реализация интерфейса IY

virtual void __stdcall Fy() { cout << "Fy" << endl; }

public:

 

// Конструктор

CA() : m_cRef(0) {}

 

// Деструктор

~CA() { trace("CA: Likvidirovat seby"); }

private:

long m_cRef;

};

HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)

{

if (iid == IID_IUnknown)

{

trace("CA QI: Vozvratit ykazateel na IUnknown");

*ppv = static_cast(this);

}

else if (iid == IID_IX)

{

trace("CA QI: Vozvratit ykazateel na IX");

*ppv = static_cast(this);

}

else if (iid == IID_IY)

{

trace("CA QI:Vozvratit ykazateel na IY");

*ppv = static_cast(this);

}

else

{

trace("CA QI: Interface No!");

*ppv = NULL;

return E_NOINTERFACE;

}

reinterpret_castAddRef();

return S_OK;

}

ULONG __stdcall CA::AddRef()

{

cout << "CA: AddRef = " << m_cRef+1 << endl;

return InterlockedIncrement(&m_cRef);

}

ULONG __stdcall CA::Release()

{

cout << "CA: Release = " << m_cRef-1 << endl;

if (InterlockedDecrement(&m_cRef) == 0)

{

delete this;

return 0;

}

return m_cRef;

}

//

 

 

// Функция создания

//

IUnknown* CreateInstance()

{

IUnknown* pI = static_cast(new CA);

pI->AddRef();

return pI;

}

//

// IID

//

// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}

static const IID IID_IX =

{0x32bb8320, 0xb41b, 0x11cf,

{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}

static const IID IID_IY =

{0x32bb8321, 0xb41b, 0x11cf,

{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

// {32bb8322-b41b-11cf-a6bb-0080c7b2d682}

static const IID IID_IZ =

{0x32bb8322, 0xb41b, 0x11cf,

{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

//

// Клиент

//

int main()

{

HRESULT hr;

trace("Client: Polychit ykazatel IUnknown");

IUnknown* pIUnknown = CreateInstance();

trace("Client: Polychit Interface IX");

IX* pIX = NULL;

hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);

if (SUCCEEDED(hr))

{

trace("Client: IX polychen");

pIX->Fx(); // Использовать интерфейс IX

pIX->Release();

}

trace("Client: Polychit Interface IY");

IY* pIY = NULL;

hr = pIUnknown->QueryInterface(IID_IY, (void**)&pIY);

if (SUCCEEDED(hr))

{

trace("Client: IY polychen");

pIY->Fy(); // Использовать интерфейс IY

pIY->Release();

}

trace("Client: Zaprosit nepodderjivaemue Interface");

IZ* pIZ = NULL;

hr = pIUnknown->QueryInterface(IID_IZ, (void**)&pIZ);

if (SUCCEEDED(hr))

{

trace("Client: Interface IZ polychen");

pIZ->Fz();

pIZ->Release();

}

else

{

trace("Client: No! Interface IZ");

}

trace("Client: Osvobodit Interface IUnknown");

pIUnknown->Release();

getch();

return 0;

}

 

Результат работы программы:

 

 

Вывод:

В этом задании мы добавили подсчет ссылок. Для этого к компоненту добавили реализацию двух методов IUnknown AddRef и Release, используя функции Win32 InterlockedIncrement и InterlockedDecrement. Функцию AddRef вызывают CreateInstance и QueryInterface для соответствующих указателей на интерфейсы. Вызовы Release добавили в клиенте, чтобы обозначить окончание работы с различными интерфейсами. Ликвидировали компонент с помощью деструктора.