Распределенная обработка данных
Контрольная работа - Компьютеры, программирование
Другие контрольные работы по предмету Компьютеры, программирование
аз, когда Вы копируете указатель на интерфейс, надо увеличить его счетчик ссылок. В приведенном далее фрагменте кода делается еще одна ссылка на интерфейс 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 добавили в клиенте, чтобы обозначить окончание работы с различными интерфейсами. Ликвидировали компонент с помощью деструктора.