Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Shpora_ROD_1.docx
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
1.09 Mб
Скачать

Билет №18

1. Модель разнородной распределенной системы

Реальные распределенные системы являются типично разнородными. Разнородность системы обусловлена двумя главными причинами:

  1. разнородностью процессоров, находящихся в узлах;

  2. разнородностью каналов передачи данных, соединяющих пары процессоров.

Разнородность процессоров и каналов передачи данных проявляется в вариациях значений их главных параметров в широких диапазонах. Так тактовые частоты процессоров и скорости в каналах передачи данных могут изменяться в разы.

Как следствие, предположение о константном времени решения задач и константном времени передачи данных от одной задачи к другой не совсем соответствует свойствам разнородной системы.

2. Управление временем жизни компонента. Подсчет ссылок

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

AddRef и Release реализуют технику управления памятью, известную как подсчет ссылок (reference counting). Подсчет ссылок — простой и быстрый способ, позволяющий компонентам самим удалять себя. Компонент СОМ поддерживает счетчик ссылок. Когда клиент получает некоторый интерфейс, значение счетчика инкрементируется. Когда клиент заканчивает работу с интерфейсом, значение декрементируется. Когда оно доходит до нуля, компонент удаляет себя из памяти. Клиент также увеличивает счетчик ссылок, когда создает новую ссылку на уже имеющийся у него интерфейс. Увеличивается счетчик вызовом AddRef, уменьшается — вызовом Release. Для подсчета ссылок необходимо использовать три правила:

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

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

3. Вызывайте AddRef после присваивания одного указателя на интерфейс другому.

Клиент должен работать с каждым интерфейсом так, как если бы у того был отдельный счетчик ссылок.

Пример компонента, косвенно наследующего интерфейс IUnknown:

class COMP : public IType_1, public IType_2 {

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

virtual ULONG __stdcall AddRef();

virtual ULONG __stdcall Release();

virtual void __stdcall operT1(int a, int b, int* pr) { *pr = a + b; }

virtual void __stdcall operT2(int c, int d, int* ps) { *ps = c * d; }

public:

COMP() : m_cRef(0) {}

~COMP() { cout<< s_conv("Самоликвидация компонента при m_cRef = 0")<<endl; }

private:

long m_cRef;

};

Реализация функции AddRef:

ULONG __stdcall COMP::AddRef() {

return InterlockedIncrement(&m_cRef);

}

Реализация функции Release:

ULONG __stdcall COMP::Release() {

if (InterlockedDecrement(&m_cRef) == 0) {

delete this;

return 0;

}

return m_cRef;

}

Функции AddRef и Release реализуются при помощи функци1 InterlockedIncrement и InterlockedDecremen,t гарантирующих изменение в каждый момент времени значения переменной m_cRef только одним потоком управления.

Задача - Дать пример определения компонента на языке С++ в модели COM

//объявление компонента

class COMP: public IType_1, public IType_2 {

public: // IUnknown

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

virtual ULONG __stdcall AddRef();

virtual ULONG __stdcall Release();

COMP();

~COMP();

//IType_1virtual void __stdcall operT1(int a, int b, int* c);

//IType_2 virtual void __stdcall operT2(int a, int b, int* c);

private:long m_cRef;//счетчик ссылок

};//определение компонентаCOMP::COMP():m_cRef(1) {

InterlockedIncrement(&g_cComponents);}COMP::~COMP() {

InterlockedDecrement(&g_cComponents); }

void COMP::operT1(int a, int b, int* c) { *c = a + b;

}void COMP::operT2(int a, int b, int* c) {

*c = a * b;

}

HRESULT __stdcall COMP::QueryInterface(const IID& iid, void** ppv) {

if (iid == IID_IUnknown) {

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

}

else if (iid == IID_IType_1) {

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

}

else if (iid == IID_IType_2) {

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

} else {

*ppv = NULL;

return E_NOINTERFACE;

}

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

return S_OK;

}

ULONG __stdcall COMP::AddRef() {

return InterlockedIncrement(&m_cRef);

}

ULONG __stdcall COMP::Release() {

if (InterlockedDecrement(&m_cRef) == 0)

{

delete this;

return 0;

}

return m_cRef;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]