2. По завершении работы вызывайте Release. Когда Вы закончили работу с интерфейсом, следует вызвать для него Release.

3. Вызывайте AddRef после присваивания. Когда бы Вы ни присваивали один указатель на интерфейс другому, вызывайте AddRef. Иными словами: следует увеличить счетчик ссылок каждый раз, когда создается новая ссылка на данный интерфейс.

Приведенный ниже фрагмент кода создает компонент и получает указатель на интерфейс IX. Мы не вызываем AddRef, так как за нас это делают CreateInstance и QueryInterface. Однако мы вызываем Release как для интерфейса IUnknown, возвращенного CreateInstance, так и для интерфейса IX, возвращенного QueryInterface.

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

IUnknown* pIUnknown = CreateInstance();

// Получить интерфейс IX

IX* pIX = NULL;

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

if (SUCCEEDED(hr))

{

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

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

}

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

В приведенном выше примере мы фактически закончили работать с IUnknown сразу же после вызова

QueryInterface, так что его можно освободить раньше.

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

IUnknown* pIUnknown = CreateInstance();

// Получить интерфейс IX

IX* pIX = NULL;

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

// Завершить работу с IUnknown

pIUnknown->Release();

// Использовать IX, если он был получен успешно

if (SUCCEEDED(hr))

{

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

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

}

Легко забыть, что всякий раз, когда Вы копируете указатель на интерфейс, надо увеличить его счетчик ссылок. В приведенном далее фрагменте кода делается еще одна ссылка на интерфейс 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<IX*>(this);

}

else if (iid == IID_IX)

{

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

*ppv = static_cast<IX*>(this);

}

else if (iid == IID_IY)

{

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

*ppv = static_cast<IY*>(this);

}

else

{

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

*ppv = NULL;

return E_NOINTERFACE;

}

reinterpret_cast<IUnknown*>(*ppv)->AddRef();

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<IX*>(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 добавили в клиенте, чтобы обозначить окончание работы с различными интерфейсами. Ликвидировали компонент с помощью деструктора.


Информация о работе «Распределенная обработка данных»
Раздел: Информатика, программирование
Количество знаков с пробелами: 22503
Количество таблиц: 0
Количество изображений: 3

Похожие работы

Скачать
28863
0
0

... ЭВМ. Особенностью этого способа является отделение технологически и по времени процедуры обработки от процедур сбора, подготовки и ввода данных.   1.3 Комплекс технических средств обработки информации Комплекс технических средств обработки информации – это совокупность автономных устройств сбора, накопления, передачи, обработки и представления информации, а также средств оргтехники, управления ...

Скачать
192976
8
10

... в пенсионный фонд (1% от зарплаты) 1345 Затраты на эксплуатацию оборудования (амортизацию) 976000 ИТОГО: 1207213 Заключение За время работы над дипломным проектом по теме «Организация удаленного доступа к распределенным базам данных» были изучены теоретические основы построения распределенных информационных систем с возможностью оперативного удаленного доступа к данным. ...

Скачать
26696
11
0

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

Скачать
158931
0
1

... дискретного программирование для решения задач проектирование систем обработки данных. -  Сформулированы задачи диссертационного исследования. 2. БЛОЧНО-СИММЕТРИЧНЫЕ МОДЕЛИ И МЕТОДЫ ПРОЕКТИРОВАНИЯ СИСТЕМ ОБРАБОТКИ ДАННЫХ В данном разделе рассматриваются общая постановка блочно-симметричной задачи дискретного программирования, её особенности и свойства. Разработан общий подход решения задач ...

0 комментариев


Наверх