-->

Сущность технологии СОМ. Библиотека программиста

На нашем литературном портале можно бесплатно читать книгу Сущность технологии СОМ. Библиотека программиста, Бокс Дональд-- . Жанр: Программирование. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
Сущность технологии СОМ. Библиотека программиста
Название: Сущность технологии СОМ. Библиотека программиста
Дата добавления: 16 январь 2020
Количество просмотров: 277
Читать онлайн

Сущность технологии СОМ. Библиотека программиста читать книгу онлайн

Сущность технологии СОМ. Библиотека программиста - читать бесплатно онлайн , автор Бокс Дональд

В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

1 ... 70 71 72 73 74 75 76 77 78 ... 118 ВПЕРЕД
Перейти на страницу:

assert (SUCCEEDED(hr));

}

;

;

;

}

Пусть класс Rect является внутрипроцессным и помечен как ThreadingModel = «Both». Разработчик данного Rect -объекта всегда будет выполняться в апартаменте потока, вызывающего CoCreateInstance (CLSID_Rect). Это означает, что два вызова CoCreateInstance (CLSID_Point) будут также выполняться в апартаменте клиента. Правила же СОМ гласят, что элементы данных m_pPtTopLeft и m_pPtBottomRight могут быть доступны только из того апартамента, который выполняет вызовы CoCreateInstance.

Похоже на то, что по меньшей мере один из методов Rect использует в своей работе два интерфейсных указателя в качестве элементов данных:

STDMETHODIMP Rect::get_Area(long *pn) {

long top, left, bottom, right;

HRESULT hr = m_pPtTopLeft->GetCoords(&left, &top);

assert(SUCCEEDED(hr));

hr = m_pPtBottomRight->GetCoords(&right, &bottom);

assert (SUCCEEDED (hr));

*pn = (right – left) * (bottom – top);

return S_OK;

}

Если бы класс Rect должен был использовать FTM, тогда можно было бы вызывать этот метод из апартаментов, отличных от того апартамента, который осуществлял начальные вызовы CoCreateInstance. К сожалению, это заставило бы метод get_Area нарушить правила СОМ, поскольку два элемента данных – интерфейсные указатели – являются легальными только в исходном апартаменте. Если бы класс Point также использовал FTM, то формально это не было бы проблемой. Тем не менее, в общем случае клиенты (такие, так класс Rect), не должны делать допущений относительно этой специфической исключительно для реализаций детали. Фактически, если объекты Point не используют FTM и окажутся созданными в другом апартаменте из-за несовместимости с ThreadingModel, то в этом случае объект Rect содержал бы указатели на заместители. Известно, что заместители четко следуют правилам СОМ и послушно возвращают RPC_E_WRONG_THREAD в тех случаях, когда к ним обращаются из недопустимого апартамента.

Это оставляет разработчику Rect выбор между двумя возможностями. Одна из них – не использовать FTM и просто принять к сведению, что когда клиенты передают объектные ссылки Rect между апартаментами, то для обращения к экземплярам класса Rect будет использоваться ORPC. Это действительно является простейшим решением, так как оно не добавляет никакого дополнительного кода и будет работать, не требуя умственных усилий. Другая возможность – не содержать исходные интерфейсные указатели как элементы данных, а вместо этого держать в качестве элементов данных некую маршалированную форму интерфейсного указателя. Именно для этого и предназначена глобальная интерфейсная таблица (Global Interface Table – GIT). Для реализации данного подхода в классе Rect следовало бы иметь в качестве элементов данных не исходные интерфейсные указатели, а «закладку» (cookies) DWORD:

class SafeRect : public IRect {

LONG m_cRef;

// СОМ reference count

// счетчик ссылок СОМ IUnknown *m_pUnkFTM;

// cache for FTM lazy aggregate

// кэш для отложенного агрегирования FTM

DWORD m_dwTopLeft;

// GIT cookie for top/left

// закладка GIT для верхнего/левого

DWORD m_dwBottomRight;

// GIT cookie for bottom/right

// закладка GIT для нижнего/правого

Разработчик по-прежнему создает два экземпляра Point, но вместо хранения исходных указателей регистрирует интерфейсные указатели с помощью глобальной таблицы GIT:

SafeRect::SafeRect(void) : m_cRef(0), m_pUnkFTM(0) {

// assume ptr to GIT is initialized elsewhere

// допустим, что указатель на GIT инициализирован

// где-нибудь в другом месте

extern IGIobalInterfaceTable *g_pGIT;

assert(g_pGIT != 0);

IPoint *pPoint = 0;

// create instance of class Point

// создаем экземпляр класса Point HRESULT

hr = CoCreateInstance(CLSID_Point, 0, CLSCTX_INPROC, IID_Ipoint, (void**)&pPoint);

assert (SUCCEEDED (hr));

// register interface pointer in GIT

// регистрируем интерфейсный указатель в GIT

hr = g_pGIT->RegisterInterfaceInGlobal(pPoint, IID_Ipoint, &m_dwTopLeft);

assert(SUCCEEDED(hr));

pPoint->Release();

// reference is now held in GIT

// ссылка теперь содержится в GIT

// create instance of class Point

// создаем экземпляр класса Point

hr = CoCreateInstance(CLSID_Point, 0, CLSCTX_INPROC, IID_Ipoint, (void**)&pPoint);

assert(SUCCEEDED(hr));

// register interface pointer in GIT

// регистрируем интерфейсный указатель в GIT

hr = g_pGIT->RegisterInterfaceInGlobal(pPoint, IID_Ipoint, &m_dwBottomRight);

assert(SUCCEEDED(hr)); pPoint->Release();

// reference is now held in GIT

// ссылка теперь содержится в GIT

}

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

Поскольку класс был преобразован для использования GIT вместо исходных интерфейсных указателей, он должен демаршалировать новый заместитель в каждом вызове метода, которому требуется доступ к зарегистрированным интерфейсам:

STDMETHODIMP SafeRect::get_Area(long *pn) {

extern IGlobalInterfaceTable *g_pGIT; assert(g_pGIT != 0);

// unmarshal the two interface pointers from the GIT

// демаршалируем дВа интерфейсных указателя из GIT

IPoint *ptl = 0, *pbr = 0;

HRESULT hr = g_pGIT->GetInterfaceFromGlobal(m_dwPtTopLeft, IID_Ipoint, (void**)&ptl);

assert (SUCCEEDED(hr));

hr = g_pGIT->GetInterfaceFromGlobal(m_dwPtBottomRight, IID_Ipoint, (void**)&pbr);

// use temp ptrs to implement method

// дпя реализации метода используем временные указатели

long top, left, bottom, right;

hr = ptl->GetCoords(&left, &top);

assert (SUCCEEDED(hr));

hr = pbr->GetCoords(&right, &bottom);

assert (SUCCEEDED (hr));

*pn = (right – left) * (bottom – top);

// release temp ptrs. // освобождаем временные указатели

ptl->Release();

pbr->Release();

return S_OK;

}

Поскольку реализация SafeRect использует FTM, то нецелесообразно пытаться сохранить немаршалированные интерфейсные указатели между вызовами метода, так как неизвестно, произойдет ли следующий вызов метода в том же самом апартаменте.

Все зарегистрированные интерфейсные указатели будут храниться в таблице GIT до тех пор, пока они не будут явно удалены нз GIT. Это означает, что класс SafeRect должен явно аннулировать элементы GIT для двух своих элементов данных:

SafeRect::~SafeRect(void) {

extern IGlobalInterfaceTable *g_pGIT;

assert(g_pGIT != 0);

HRESULT hr = g_pGIT->RevokeInterfaceFromGlobal(m_dwTopLeft);

assert(SUCCEEDED(hr));

hr = g_pGIT->RevokeInterfaceFromGlobal(m_dwBottomRight);

assert(SUCCEEDED(hr));

}

Удаление интерфейсного указателя из GIT освобождает все хранящиеся ссылки на объект.

Отметим, что совместное использование GIT и FTM влечет за собой очень много обращений к GIT, которые будут сделаны для создания временных интерфейсных указателей, необходимых для использования в каждом отдельном методе. Хотя GIT оптимизирована именно для поддержки такой схемы использования, код остается однообразным. Следующий простой класс C++ скрывает использование «закладки» GIT за удобным интерфейсом, обеспечивающим безопасность типа:

1 ... 70 71 72 73 74 75 76 77 78 ... 118 ВПЕРЕД
Перейти на страницу:
Комментариев (0)
название