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

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

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

9; ykazatel na IUnknown");

IUnknown* pIUnknown = CreateInstance();

trace("Client: Polychit ykazatel na IX");

IX* pIX = NULL;

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

if (SUCCEEDED(hr))

{

trace("Client: IX polychen");

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

}

trace("Client: Polychit ykazatel na IY");

IY* pIY = NULL;

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

if (SUCCEEDED(hr))

{

trace("Client: IY polychen");

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

}

trace("Client: Zaprosit nepodderjivaemuy interface");

IZ* pIZ = NULL;

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

if (SUCCEEDED(hr))

{

trace("Client: Interface IZ polychen");

pIZ->Fz();

}

else

{

trace("Client: No Interface IZ");

}

trace("Client: Polychit Interface IY cherez Interface IX");

IY* pIYfromIX = NULL;

hr = pIX->QueryInterface(IID_IY, (void**)&pIYfromIX);

if (SUCCEEDED(hr))

{

trace("Client: IY polychen");

pIYfromIX->Fy();

}

trace("Client: Polechit Interface IUnknown cherez IY");

IUnknown* pIUnknownFromIY = NULL;

hr = pIY->QueryInterface(IID_IUnknown, (void**)&pIUnknownFromIY);

if (SUCCEEDED(hr))

{

cout << "Sovpadaut li ykazateli na IUnknown? ";

if (pIUnknownFromIY == pIUnknown)

{

cout << "Yes, pIUnknownFromIY == pIUnknown" << endl;

}

else

{

cout << "No, pIUnknownFromIY != pIUnknown" << endl;

}

}

 

// Удалить компонент

delete pIUnknown;

getch();

return 0;

}

 

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

 

Вывод:

 

В данном задании объявили интерфейсы IX, IY, IZ, и интерфейс IUnknown.

Реализовали компонент. Класс СА который реализует компонент, поддерживающий интерфейсы IX и IY. Реализовали QueryInterface. Функцию CreateInstance, которая определяется после класса CA. Клиент использует ее, чтобы создать компонент, представляемый при помощи СА, и получили указатель на IUnknown этого компонента.

 

Задание №1B Подсчет ссылок

 

Цель работы:

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

Ликвидировать компонент с помощью деструктора.

Теоретические сведения:

Вместо того, чтобы удалять компоненты напрямую, мы будем сообщать компоненту, что нам нужен интерфейс или что мы закончили с ним работать. Мы точно знаем, когда начинаем использовать интерфейс, и знаем (обычно), когда перестаем его использовать. Однако, как уже ясно, мы можем не знать, что закончили использовать компонент вообще. Поэтому имеет смысл ограничиться сообщением об окончании работы с данным интерфейсом и пусть компонент сам отслеживает, когда мы перестаем пользоваться всеми интерфейсами.

Именно для реализации этой стратегии и предназначены еще две функции-члена IUnknown AddRef и Release.

 

определение интерфейса IUnknown:

 

interface IUnknown

{

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

virtual ULONG __stdcall AddRef() = 0;

virtual ULONG __stdcall Release() = 0;

};

 

AddRef и Release реализуют и технику управления памятью, известную как подсчет ссылок (reference counting).

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

Для того, чтобы пользоваться подсчетом ссылок, необходимо знать лишь три простых правила:

1. Вызывайте AddRef перед возвратом. Функции, возвращающие интерфейсы, перед возвратом всегда

должны вызывать AddRef для соответствующего указателя. Это также относится к QueryInterface и функции CreateInstance. Таким образом, Вам не нужно вызывать AddRef в своей программе после получения (от функции) указателя на интерфейс.

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

}

 

Легко забыть, что всякий р