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

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




⚡ 👉🏻👉🏻👉🏻 ИНФОРМАЦИЯ ДОСТУПНА ЗДЕСЬ ЖМИТЕ 👈🏻👈🏻👈🏻




























































Задание №1 Реализация интерфейса COM
Разработать
код на С++, реализующий простой интерфейс СОМ без динамической компоновки:
-      
клиент
и компонент взаимодействуют через два интерфейса IX иIY, интерфейсы COM
реализованы как чисто абстрактные базовые классы С++;
-      
в
качестве клиента использовать процедуру main;
-      
компонент
реализуется классом СА, который наследует как IX так и IY;
-      
класс
СА реализует функции-члены обоих интерфейсов (множественное наследование);
-      
клиент
создает экземпляр компонента (для управления существованием компонента клиент
применяет оператора new и delete), далее он получает указатели на интерфейсы, поддерживаемые
компонентом, использовать эти указатели анологично указателям на классы С++;
-      
выводить
промежуточные сообщения при использовании интерфейсов IX и IY;
-      
вместо
определения интерфейса как класса использовать определение из заголовочного
файла OBJBASE.H
В СОМ интерфейсы — это все. Для клиента компонент представляет
собой набор интерфейсов. Клиент может взаимодействовать с компонентом СОМ
только через интерфейс. С точки зрения программиста СОМ, интерфейсы — важная
часть любого приложения. Компоненты сами по себе есть просто детали реализации
интерфейсов.
Утверждение, что компонент — всего лишь деталь реализации
интерфейса, конечно, преувеличение. В конце концов, интерфейс без реализации
ничего не сделает. Однако компонент можно удалить и заменить другим; если новый
компонент поддерживает те же интерфейсы, что и старый, приложение будет
работать по-прежнему. Отдельные компоненты сами по себе не определяют
приложения. Приложение определяют интерфейсы между компонентами. Пока
интерфейсы неизменны, компоненты могут появляться и исчезать
Теперь рассмотрим код, реализующий простой интерфейс. В
приведенном ниже тексте программы компонент CA использует IX и IY для реализации двух
интерфейсов.
class
CA : public IX, public IY // Компонент
// Реализация
абстрактного базового класса IX
virtual
void Fx1() { cout << “Fx1” << endl; }
virtual
void Fx2() { cout << “Fx2” << endl; }
//
Реализация абстрактного базового класса IY
virtual
void Fy1() { cout << “Fy1” << endl; }
virtual
void Fy2() { cout << “Fy2” << endl; }
IX и IY — это чисто абстрактные базовые классы, которые используются для
реализации интерфейсов. Чистоабстрактный базовый класс (pure abstract base class) — это базовый класс,
который содержит только чисто виртуальные функции (pure virtual functions). Чисто виртуальная
функция — это виртуальная функция, «помеченная =0 — знаком спецификатора
чистоты (pure specifier). Чисто виртуальные функции не реализуютсяв классах, в которых
объявлены. Как видно из приведенного выше примера, функции IX::Fx1, IX::Fx2, IY::Fy1 и IY::Fy2 только декларируются.
Реализуются же они в производном классе. В приведенном фрагменте кода компонент
CA наследует два чисто
абстрактных базовых класса — IX и IY — и реализует их чисто виртуальные функции.
Для того, чтобы реализовать функции-члены IX и IY, CA использует множественное
наследование. Последнее означает, что класс является производным более чем от
одного базового класса. Класс С++ чаще всего использует единичное наследование,
т.е. имеет только один базовый класс.
#include
"objbase.h" // Определить интерфейс
void
trace(const char* pMsg) { cout << pMsg << endl; }
virtual void
__stdcall Fx1() { cout << "CA::Fx1" << endl; }
virtual void
__stdcall Fx2() { cout << "CA::Fx2" << endl; }
virtual void
__stdcall Fy1() { cout << "CA::Fy1" << endl; }
virtual void
__stdcall Fy2() { cout << "CA::Fy2" << endl; }
trace("Client:
Sozdanie ekzemplyra komponenta");
trace("Client:
Ispol'zovanie interface IX");
trace("Client:
Ispol'zovanie interface IY");
В данном
задании мы реализововали простой интерфейс СОМ без динамической компоновки. Интерфейсы
COM реализованы как чисто абстрактные базовые классы С++, в качестве клиента
использовали процедуру main.
1.        
Объявить
интерфейсы IX, IY, IZ . Объявить интерфейс IUnknown.
2.        
Реализация
компонента. Класс СА реализует компонент, поддерживающий интерфейсы IX и IY. Реализовать QueryInterface описанным выше способом.
Функцию CreateInstance определить после класса CA. Клиент использует ее,
чтобы создать компонент, представляемый при помощи СА, и получить указатель на IUnknown этого компонента. После CreateInstance определить IID для интерфейсов. (Для
того, чтобы определить IID для IUnknown компоновать с UUID.LIB).
3.        
Реализация
клиента, роль которого выполняет main. Клиент начинает с создания компонента при
помощи CreateInstance. CreateInstance возвращает указатель на интерфейс IUnknown компонента. Клиент при
помощи QueryInterface запрашивает через интерфейс IUnknown указатель на интерфейс IX компонента. Анологично
запросить и IY. Использовать эти указатели для доступа к функциям-членам.
Запросить интерфейс IZ. QueryInterface возвращает код ошибки, так как СА не реализует IZ. Далее Клиент
запрашивает указатель на интерфейс IY через указатель на интерфейс IX, pIX. Поскольку компонент
поддерживает IY, этот запрос будет успешным, и клиент сможет использовать
возвращенный указатель на интерфейс IY так же, как он использовал первый указатель.
Затем клиент запрашивает интерфейс IUnknown через указатель на IY. Поскольку все
интерфейсы COM наследуют IUnknown, этот запрос должен быть успешным, причем
возвращенный указатель совпадет с первым указателем, так как . QueryInterface возвращает один и тот же
указатель на все запросы к IUnknown.
В COM клиент взаимодействует с
компонентом с помощью интерфейса
IUnknown, который определен в
заголовочном файле UNKWN.H:
virtual
HREZULT --stdcall QueryInterface( const IID&iid,
virtual
ULONG --stdcall Addref( ) = 0 ;
virtual ULONG --stdcall
Release( ) = 0 ;
Функцию с
именем QueryInterface клиент вызывает, чтобы определить, поддерживает ли компонент
некоторый интерфейс. У функции QueryInterface два параметра. Первый
параметр – идентификатор интерфейса. Второй параметр - адрес, по которому QueryInterface помещает указатель на
искомый интерфейс.
QueryInterface возвращает HREZULT – 32-разрядный код
результата.
QueryInterface может возвратить либо S_OK, либо E_NOINTERFACE. Клиент не должен прямо
сравнивать возвращаемое QueryInterface значение с этими константами; для проверки надо
использовать макросы SUCCEEDED или FAILED.
Для получения
указателя на IUnknown использовать функцию, например, CreateInstance которая создает
компонент и возвращает указатель на IUnknown:
IUnknown * pI
= static_cast(new CA) ;
Предположим,
что у нас есть указатель на IUnknown, pI. Чтобы определить, можно ли использовать
некоторый другой интерфейс, мы вызываем QueryInterface, передавая ей
идентификатор нужного нам интерфейса. Если QueryInterface отработала успешно, мы
можем пользоваться указателем:
// Определить указатель
на интерфейс
HREZULT hr = pI-> QueryInterface(IID_IX, (void**)&pIX) ;
Запишем QueryInterface для следующего
компонента, реализуемого классом CA:
Class CA : public
IX, public IY { /*…*/ } ;
Следующий фрагмент кода
реализует QueryInterface для класса, приведенного выше фрагмента кода.
HREZULT --stdcall
CA:: QueryInterface( const IID&iid, void * * ppv);
// Клиент
запрашивает интерфейс IUnknown
// Мы не поддерживаем
запрашиваемый клиентом интерфейс.
// Установить возвращаемый
указатель в NULL.
static_cast<
IUnknown*>(*ppv)->AddRef( ) ;
void
trace(const char* msg) { cout << msg << endl; }
virtual
HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG
__stdcall AddRef() { return 0; }
virtual ULONG
__stdcall Release() { return 0; }
virtual void
__stdcall Fx() { cout << "Fx" << endl; }
virtual void
__stdcall Fy() { cout << "Fy" << endl; }
HRESULT
__stdcall CA::QueryInterface(const IID& iid, void** ppv)
trace("QueryInterface:
Vernyt' ykazatel' na IUnknown");
trace("QueryInterface:
Vernyt' ykazatel' na IX");
trace("QueryInterface:
Vernyt' ykazatel' na IY");
trace("QueryInterface:
Interface No!");
reinterpret_cast(*ppv)->AddRef();
IUnknown* pI =
static_cast(new CA);
//
{32bb8320-b41b-11cf-a6bb-0080c7b2d682}
{0xa6, 0xbb,
0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
//
{32bb8321-b41b-11cf-a6bb-0080c7b2d682}
{0xa6, 0xbb,
0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
//
{32bb8322-b41b-11cf-a6bb-0080c7b2d682}
{0xa6, 0xbb,
0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
trace("Client:
Polychit' ykazatel' na IUnknown");
IUnknown*
pIUnknown = CreateInstance();
trace("Client:
Polychit' ykazatel' na IX");
hr =
pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIX->Fx(); //
Использовать интерфейс IX
trace("Client:
Polychit' ykazatel na IY");
hr =
pIUnknown->QueryInterface(IID_IY, (void**)&pIY);
pIY->Fy(); //
Использовать интерфейс IY
trace("Client:
Zaprosit' nepodderjivaemuy interface");
hr =
pIUnknown->QueryInterface(IID_IZ, (void**)&pIZ);
trace("Client:
Interface IZ polychen");
trace("Client:
Polychit' Interface IY cherez Interface IX");
hr =
pIX->QueryInterface(IID_IY, (void**)&pIYfromIX);
trace("Client:
Polechit' Interface IUnknown cherez IY");
hr =
pIY->QueryInterface(IID_IUnknown, (void**)&pIUnknownFromIY);
cout <<
"Sovpadaut li ykazateli na IUnknown? ";
cout <<
"Yes, pIUnknownFromIY == pIUnknown" << endl;
cout <<
"No, pIUnknownFromIY != pIUnknown" << endl;
В данном
задании объявили интерфейсы IX, IY, IZ, и интерфейс IUnknown.
Реализовали
компонент. Класс СА который реализует компонент, поддерживающий интерфейсы IX и IY. Реализовали QueryInterface. Функцию CreateInstance, которая определяется после
класса CA. Клиент использует ее, чтобы создать компонент, представляемый
при помощи СА, и получили указатель на IUnknown этого компонента.
Добавить к
предыдущей программе из лабороторной работы №1А подсчет ссылок. Для этого к
компоненту добавить реализации двух методов IUnknown – AddRef и Release.используя функции Win32 InterlockedIncrement и InterlockedDecrement. Функцию AddRef вызывают CreateInstance и QueryInterface для соответствующих
указателей на интерфейсы. Вызовы Release добавить в клиенте, чтобы обозначить окончание
работы с различными интерфейсами.
Ликвидировать
компонент с помощью деструктора.
Вместо того, чтобы удалять компоненты напрямую, мы будем сообщать
компоненту, что нам нужен интерфейс или что мы закончили с ним работать. Мы
точно знаем, когда начинаем использовать интерфейс, и знаем (обычно), когда перестаем
его использовать. Однако, как уже ясно, мы можем не знать, что закончили
использовать компонент вообще. Поэтому имеет смысл ограничиться сообщением об
окончании работы с данным интерфейсом — и пусть компонент сам отслеживает,
когда мы перестаем пользоваться всеми интерфейсами.
Именно для реализации этой стратегии и предназначены еще две
функции-члена IUnknown — AddRef и Release.
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();
HRESULT
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIX->Fx();
// Использовать интерфейс IX
pIX->Release(); // Завершить работу с
IX
pIUnknown->Release(); // Завершить работу с
Iunknown
В приведенном выше примере мы фактически закончили работать с IUnknown сразу же после вызова
QueryInterface, так что его можно
освободить раньше.
IUnknown*
pIUnknown = CreateInstance();
HRESULT
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
//
Использовать IX, если он был получен успешно
pIX->Fx(); // Использовать
интерфейс IX
pIX->Release(); // Завершить работу с
IX
Легко забыть, что всякий раз, когда Вы копируете указатель на
интерфейс, надо увеличить его счетчик ссылок. В приведенном далее фрагменте
кода делается еще одна ссылка на интерфейс IX. В общем случае
необходимо увеличивать счетчик ссылок всякий раз, когда создается копия
указателя на интерфейс, о чем говорит приведенное выше правило 3.
IUnknown*
pIUnknown = CreateInstance();
HRESULT
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIX->Fx(); // Использовать
интерфейс IX
IX* pIX2 = pIX; // Создать копию pIX
pIX2->AddRef(); // Увеличить счетчик
ссылок
pIX2->Fx(); // Что-то делать при
помощи pIX2
pIX2->Release(); // Завершить работу с
pIX2
pIX->Release(); // Завершить работу с
pIX
Клиент сообщает компоненту о своем желании использовать интерфейс,
когда вызывается
QueryInterface. QueryInterface вызывает AddRef для запрашиваемого
интерфейса. Когда клиент заканчивает работу с интерфейсом, он вызывает для
этого интерфейса Release. Компонент остается в памяти, ожидая, пока счетчик ссылок не
станет равен 0. Когда счетчик становится нулем, компонент сам себя удаляет.
void
trace(const char* msg) { cout << msg << endl; }
virtual
HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual void
__stdcall Fx() { cout << "Fx" << endl; }
virtual void
__stdcall Fy() { cout << "Fy" << endl; }
~CA() {
trace("CA: Likvidirovat' seby"); }
HRESULT
__stdcall CA::QueryInterface(const IID& iid, void** ppv)
trace("CA
QI: Vozvratit' ykazateel na IUnknown");
trace("CA
QI: Vozvratit' ykazateel na IX");
trace("CA
QI:Vozvratit' ykazateel na IY");
reinterpret_cast(*ppv)->AddRef();
cout <<
"CA: AddRef = " << m_cRef+1 << endl;
return
InterlockedIncrement(&m_cRef);
cout <<
"CA: Release = " << m_cRef-1 << endl;
if
(InterlockedDecrement(&m_cRef) == 0)
IUnknown* pI =
static_cast(new CA);
//
{32bb8320-b41b-11cf-a6bb-0080c7b2d682}
{0xa6, 0xbb,
0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
//
{32bb8321-b41b-11cf-a6bb-0080c7b2d682}
{0xa6, 0xbb,
0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
//
{32bb8322-b41b-11cf-a6bb-0080c7b2d682}
{0xa6, 0xbb,
0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
trace("Client:
Polychit' ykazatel IUnknown");
IUnknown*
pIUnknown = CreateInstance();
trace("Client:
Polychit' Interface IX");
hr =
pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIX->Fx(); // Использовать
интерфейс IX
trace("Client:
Polychit' Interface IY");
hr =
pIUnknown->QueryInterface(IID_IY, (void**)&pIY);
pIY->Fy(); // Использовать
интерфейс IY
trace("Client:
Zaprosit' nepodderjivaemue Interface");
hr =
pIUnknown->QueryInterface(IID_IZ, (void**)&pIZ);
trace("Client:
Interface IZ polychen");
trace("Client:
Osvobodit' Interface IUnknown");
В этом
задании мы добавили подсчет ссылок. Для этого к компоненту добавили реализацию
двух методов IUnknown – AddRef и Release, используя функции Win32 InterlockedIncrement и InterlockedDecrement. Функцию AddRef вызывают CreateInstance и QueryInterface для соответствующих
указателей на интерфейсы. Вызовы Release добавили в клиенте, чтобы обозначить окончание
работы с различными интерфейсами. Ликвидировали компонент с помощью деструктора.

Название: Распределенная обработка данных
Раздел: Рефераты по информатике, программированию
Тип: контрольная работа
Добавлен 10:30:03 19 ноября 2010 Похожие работы
Просмотров: 87
Комментариев: 15
Оценило: 3 человек
Средний балл: 5
Оценка: неизвестно   Скачать

Срочная помощь учащимся в написании различных работ. Бесплатные корректировки! Круглосуточная поддержка! Узнай стоимость твоей работы на сайте 64362.ru
Привет студентам) если возникают трудности с любой работой (от реферата и контрольных до диплома), можете обратиться на FAST-REFERAT.RU , я там обычно заказываю, все качественно и в срок) в любом случае попробуйте, за спрос денег не берут)
Да, но только в случае крайней необходимости.

Контрольная работа: Распределенная обработка данных
Реферат: Анализ деятельности Всемирного банка по сокращению бедности в Кыргызстане
Сочинение На Тему Главная
Эссе На Тему Взгляд Со Стороны
Реферат по теме Контрреформы Александра III
Реферат по теме Экологические проблемы Персидского залива
Курсовая работа: Многозначность союзов и их перевод на русский язык
Системно Деятельностного Подхода На Уроках Биологии Курсовая
Сочинение По Опорным Словам 4 Класс
Реферат по теме Информационно-управляющая оболочка для системы ЧПУ
Реферат: Экономика как наука 2
Социология Общества Реферат
Реферат: Похідні та диференціали функції багатьох змінних
Дипломная Работа На Тему Технология Отработки Месторождения Таймырского Рудника Камерными Системами
Оказание Помощи При Тазовых Предлежаниях Реферат
Реферат: How We Listen By Aaron Copland Essay
Собрание Сочинений Любэ
Английский Язык 7 Класс Афанасьева Контрольные Работы
Реферат: Условия допустимости веры в смысл жизни. Скачать бесплатно и без регистрации
Курсовая работа по теме Разработка алгоритма обработки сигнала на основе теории восприятия информации человеком
Курсовая Работа На Тему Проект Портового Элеватора
Реферат: Десять эффектов рекламы
Курсовая работа: Скрипичное искусство в России конца XIX–начала XX веков
Реферат: Основы права

Report Page