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