Дональд Бокс - Сущность технологии СОМ. Библиотека программиста
- Название:Сущность технологии СОМ. Библиотека программиста
- Автор:
- Жанр:
- Издательство:Питер
- Год:2001
- Город:СПб
- ISBN:5-318-00058-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Дональд Бокс - Сущность технологии СОМ. Библиотека программиста краткое содержание
В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.
Сущность технологии СОМ. Библиотека программиста - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
STDMETHODIMP Object::UseCallback(ICallback *pcb) {
if (!pcb) return E_INVALIDARG;
// hold onto proxy for later use
// сохраняем в заместителе для дальнейшего использования
(m_pcbMyCaller = pcb)->AddRef();
return S_OK; }
Обратное соединение с апартаментом клиента будет длиться до тех пор, пока заместитель не будет освобожден объектом. Поскольку все апартаменты СОМ могут получать ORPC-запросы, объект может послать обратный вызов в апартамент клиента в любое время.
Реентерабельность реализуется для каждого типа апартаментов по-разному. Наиболее проста реализация в случае МТА, так как МТА-апартаменты не гарантируют параллелизма и не указывают, какой поток будет обслуживать заданный вызов метода. Повторный вызов может прийти в то время, когда МТА-поток заблокирован в канале в ожидании ORPC-ответа. Тогда RPC-поток, получающий повторный запрос, просто входит в МТА и обслуживает вызов своими ресурсами. Тот факт, что другой поток апартамента заблокирован и ожидании ORPC-ответа, не влияет на диспетчеризацию вызова. В случае реализации RTA – когда поток, выполняющийся в RTA, делает межапартаментный вызов посредством заместителя, – канал уступает контроль над апартаментом, снимая блокировку всего RTA и разрешая тем самым обработку поступивших вызовов. И снова, но причине отсутствия привязки объектов к потокам в RTA, RPC-поток, получающий ORPC-запрос, может просто войти в апартамент RTA и обслужить вызов сразу после блокирования всего RTA.
Реализация реентерабельности для апартаментов STA более сложна. Поскольку STA-объекты обладают привязкой к потоку, то когда поток делает межапартаментный вызов из STA, СОМ не может разрешить потоку сделать блокирующий вызов, который предотвратил бы обработку входящих ORPC-запросов. Когда поток вызывающего объекта входит в метод канала SendReceive , чтобы послать ORPC-запрос и получить ORPC-ответ, этот канал захватывает поток вызывающего объекта и помещает его во внутренний оконный MSG -цикл. Это аналогично тому, что происходит при создании потоком модальных диалоговых окон. В обоих случаях поток вызывающего объекта вынужден обслуживать определенные классы оконных сообщений во время выполнения этой операции. В случае модальных диалоговых окон поток должен обслуживать основные оконные сообщения, чтобы разморозить основной пользовательский интерфейс. В случае межапартаментного вызова метода в СОМ поток должен обслуживать не только обычные оконные сообщения пользовательского интерфейса, но и оконные сообщения, относящиеся к поступающим ORPC-запросам. По умолчанию канал будет разрешать обслуживание всех поступающих ORPC-вызовов, пока клиентский поток ожидает ORPC-ответа. Такой режим можно настроить с помощью установки в потоке специального фильтра сообщений.
Фильтры сообщений являются уникальными для STA. Фильтр сообщений – это объект СОМ для каждого STA, который используется для решения вопроса, организовать диспетчеризацию поступающих ORPC-запросов или нет. Кроме того, фильтры сообщений используются для размещения задержанных сообщений пользовательского интерфейса, пока поток STA ожидает ORPC-ответа внутри канала. Фильтры сообщений выставляют интерфейс IMessageFilter :
[ uuid(00000016-0000-0000-C000-000000000046),local, object ]
interface IMessageFilter : IUnknown {
typedef struct tagINTERFACEINFO {
IUnknown *pUnk;
// which object?
// чей объект?
IID iid;
// which interface?
// чей интерфейс?
WORD wMethod;
// which method?
// чей метод?
} INTERFACEINFO;
// called when an incoming ORPC request arrives in an STA
// вызывается, когда входящий ORPC-запрос поступает в STA
DWORD HandleInComingCall(
[in] DWORD dwCallType,
[in] HTA5K dwThreadIdCaller,
[in] DWORD dwTickCount,
[in] INTERFACEINFO *pInterfaceInfo
);
// called when another STA rejects or postpones an ORPC request
// вызывается, когда другой STA отклоняет или откладывает ORPC-запрос
DWORD RetryRejectedCall(
[in] HTASK dwThreadIdCallee,
[in] DWORD dwTickCount,
[in] DWORD dwRejectType
);
// called when a non-COM MSG arrives while the thread is
// awaiting an ORPC response
// вызывается, когда поступает не СОМ'овское MSG, пока
// поток ожидает ORPC-ответа
DWORD MessagePending(
[in] HTASK dwThreadIdCallee,
[in] DWORD dwTickCount,
[in] DWORD dwPendingType
); }
Для установки специального фильтра сообщений в СОМ существует API-функция CoRegisterMessageFilter :
HRESULT CoRegisterMessageFilter([in] IMessageFilter *pmfNew, [out] IMessageFilter **ppmfOld);
CoRegisterMessageFilter связывает указанный фильтр сообщений с текущим STA. Предыдущий фильтр сообщений возвращается для того, чтобы вызывающий объект мог восстановить его в дальнейшем.
Когда бы входящий ORPC-запрос ни пришел в STA-поток, вызывается метод фильтра сообщений HandleIncomingCall , который дает апартаменту возможность принять, отклонить или отложить вызов. HandleIncomingCall используется как реентерабельными, так и нереентерабельными вызовами. Параметр dwCallType показывает, какой тип вызова был получен:
typedef enum tagCALLTYPE {
CALLTYPE_TOPLEVEL,
// STA not in outbound call
// STA не в исходящем вызове
CALLTYPE_NESTED,
// callback on behalf of outbound call
// обратный вызов от имени исходящего вызова
CALLTYPE_ASYNC,
// asynchronous call
// асинхронный вызов
CALLTYPE_TOPLEVEL_CALLPENDING,
// new call while waiting
// новый вызов во время ожидания
CALLTYPE_ASYNC_CALLPENDING
// async call while waiting
// асинхронный вызов во время ожидания
} CALLTYPE;
Вложенный (реентерабельный) вызов и незаконченный (нереентерабельный) вызов верхнего уровня происходят, пока поток ожидает ORPC-ответа в канале. Вызовы верхнего уровня происходят в тех случаях, когда в апартаменте нет активных вызовом.
В СОМ определено перечисление, которое должна возвратить реализация HandleIncomingCall , чтобы указать, что произошло с вызовом:
typedef enum tagSERVERCALL {
SERVERCALL_ISHANDLED,
// accept call and forward to stub
// принимаем вызов и направляем его заглушке
SERVERCALL_REJECTED,
// tell caller that call is rejected
// сообщаем вызывающему объекту, что вызов отклонен
SERVERCALL RETRYLATER
// tell caller that call is postponed
// сообщаем вызывающему объекту, что вызов отложен
} SERVERCALL;
Если функция HandleIncomingCall фильтра сообщений возвращает SERVERCALL_ISHANDLED , то вызов будет направлен в интерфейсную заглушку для демаршалинга. Фильтр сообщений, принятый по умолчанию, всегда возвращает SERVERCALL_ISHANDLED . Если HandleIncomingCall возвращает SERVERCALL_REJECTED или SERVERCALL_RETRYLATER , то фильтр сообщений вызывающего объекта будет информирован о положении вызова и ORPC-запрос будет отклонен.
Когда фильтр сообщений отвергает или откладывает вызов, то фильтр сообщений вызывающего объекта информируется об этом с помощью метода RetryRejectedCall . Этот вызов происходит в контексте апартамента вызывающего объекта, и реализация метода RetryRejectedCall фильтра сообщений может решать, повторять ли отложенный вызов. Параметр dwRejectType указывает, был ли вызов отклонен или отложен. Реализация канала вызывающего объекта будет решать, какое действие предпринять, в зависимости от значения, возвращенного RetryRejectedCall . Если RetryRejectedCall возвращает –1 , то канал предположит, что повторных попыток не требуется, и немедленно заставит заместитель возвратить HRESULT , равный RPC_E_CALL_REJECTED . По умолчанию фильтр сообщений всегда возвращает –1 . Любое другое значение, возвращаемое методом RetryRejectedCall , интерпретируется как число миллисекунд, через которое следует повторить вызов. Поскольку это согласование осуществляется внутри канала, то не требуется повторного ORPC-запроса со стороны заместителя. В сущности, интерфейсные маршалеры не имеют ни малейшего понятия о процессах в фильтре сообщений.
Читать дальшеИнтервал:
Закладка: