Добавить в цитаты Настройки чтения

Страница 190 из 372

При проектировании объекта с потоковой моделью Both нужно предусмотреть агрегацию этим объектом одного специального уже реализованного в СОМ объекта, поддерживающего специальным образом реализованный стандартный интерфейс IMarshaler.

При использовании пары функций

CoMarshaIinterThreadInterfaceInStream

и

CoGetInterfaceAndReieaseStream

система вначале проверяет — не поддерживает ли объект, указатель на который маршалируется, интерфейс IMarshal. Если такой интерфейс не поддерживается, то используется стандартный маршалинг и мы получаем прокси для доступа к объекту, так как было описано ранее. Если же интерфейс IMarshal реализован в данном объекте, то именно он определяет способ маршалинга.

Упомянутый выше агрегируемый объект реализует интерфейс IMarshal следующим образом. Прежде всего проверяется — выполняется ли маршалинг в рамках одного процесса, или между различными процессами или машинами. В первом случае в объект-поток записывается прямой указатель на запрашиваемый интерфейс, который и получает вызывающий поток при демаршализации указателя на интерфейс. Во втором случае запускается стандартный процесс маршалинга указателя на интерфейс с формированием прокси.

Создать агрегируемый объект, реализующий marshal, можно с помощью функции

CoCreateFreeThreadedMarshaleг.

При использовании описанного приема нужно соблюдать определенные ограничения. Объект с FTM не должен использовать прямые указатели на другие объекты, которые не используют FTM. Причина понятна. При нарушении указанного ограничения некоторый поток может получить косвенным образом прямой указатель на объект из другого апартамента, чья потоковая модель может отличаться от Both. Использование этого указателя может привести к краху всего приложения.

• При демаршализации указателя на интерфейс уничтожается объект-поток

Это означает, что если указатель на некоторый объект нужен потокам в нескольких различных апартаментах, то мы должны несколько раз вызывать пару функций

CoMarshaInterThreadInterfaceInStream

и

CoGetInterfaceAndReleaseStream.

Было бы удобно иметь одно общее дл всего процесса хранилище представленных в нейтральной относительно апартамента форме маршалированных указателей на пользующиеся успехом объекты. Тогда любой поток, которому нужен указатель на объект из другого апартамента, мог бы получить копию маршалированного указателя и демаршалировать его в своем апартаменте, получив соответствующий прокси.

Такая технология реализована в СОМ и называется Global Interface Table (GIT). В классе с GUID CLSID_StdGiobalInterfасеTаЫе реализован интерфейс IGlobalInterfасеаЫе, методы которого позволяют зарегистрировать новый указатель на некоторый интерфейс в этой таблице, получить его из таблицы, удалить указатель из таблицы. При этом автоматически происходит маршализация указателя на интерфейс при его регистрации в таблице и демаршализация при получении из таблицы.

А теперь в заключении рассмотрим механизм вызова метода через границу апартамента.

Начнем с механизма вызова объекта в STA.

При вызове объекта из STA вызов, пришедший из канала, преобразуется в сообщение, которое становится в очередь сообщений, связанную с данным STA. Поток, живущий в STA, выбирает из очереди очередное сообщение, которое через оконную процедуру попадает в стаб нужного интерфейса, где вновь преобразуется в вызов, который и выполняется объектом. Следующее сообщение из очереди выбирается после обработки предыдущего. Тем самым обеспечивается синхронизация вызовов объектов из STA.

Тут, однако, имеется одна тонкость. При выполнении вызова объект из этого STA может вызвать некоторый метод объекта из другого апартамента, тот из следующего и т. д. На каком-то этапе цепочка вызовов может вернуться в апартамент, где эта цепочка начиналась. Этот новый вызов в форме сообщения встанет в очередь, но очередь не двигается, т. к. поток, живущий в этом апартаменте, послал вызов за пределы своего апартамента и ждет ответа.





Для решения указанной проблемы используется следующий подход. Все такие цепочки вызовов отслеживаются (все вызовы из одной цепочки имеют одинаковый GUID). Когда в очередь приходит новый вызов с GUID, совпадающим с GUID выполняемого вызова, поток выходит из состояния ожидания и начинает выполнять вновь пришедший вызов.

В случае вызова объекта из МТА все значительно проще.

Нет никаких сообщений и их очередей. Для обработки пришедшего из канала вызова из пула связанных с МТА рабочих потоков выбирается произвольный поток. Когда этот поток должен сделать вызов за пределы апартамента, он входит в состояние ожидания, не отслеживая зависимость вновь поступающих вызовов от обрабатываемого им вызова. В пуле найдется поток, который обработает вновь пришедший вызов, и наш заснувший поток когда-нибудь получит ответ и продолжит обработку вызова.

Технология СОМ+ от Microsoft

СОМ+ можно назвать версией СОМ для Windows 2000. Но, на самом деле, это не просто очередная версия некоторого продукта. СОМ представляет собой модель компонентного программирования для локальных приложений. DCOM, хотя и предоставила возможность размещения клиента и сервера на различных машинах, является той же самой СОМ. Но СОМ+ — это уже компонентная модель для приложений, действующих на уровне предприятия. Кроме возможности удаленного вызова, которая уже была в COM/DCOM, данная модель расширяет традиционную СОМ прежде всего предоставлением важных сервисов, без которых создание распределенного приложения является крайне трудным, если не невозможным. Эти сервисы перечислены ниже

• Обеспечивают надежность приложения:

♦ Безопасность

В отличие от локального приложения, в работу с распределенным приложением вовлечены многие конечные пользователи, которые, с точки зрения администратора системы, должны иметь различные права доступа к данному приложению. В СОМ+ решаются следующие вопросы:

— Аутентификация клиента

Тот ли он, за кого себя выдает?

— Авторизация клиента

Какие операции может выполнять данный клиент?

— Передача полномочий

Часто в распределенной системе вызов некоторого метода, выполненный конечным пользователем, приводит к формированию цепочки вызовов одними объектами других объектов. В начале цепочки используются полномочия конечного пользователя. Но чьи полномочия будут использованы далее? о Транзакции

♦ Транзакции обеспечивают целостность данных в распределенной системе. Заметим, что СУБД обеспечивают механизм транзакций, но только в рамках одной базы данных. Здесь же в одну распределенную транзакцию могут быть вовлечены различные независимые хранилища данных,

♦ Синхронизация

В СОМ синхронизация доступа к объектам из разных потоков осуществляется с помощью использования механизма апартаментов. Практика программирования показывает, что редкие программисты проектируют потоко-безопасные компоненты, которые могут жить в таких апартаментах как МТА и NA. Как правило, используется STA, и доступ ко всем объектам, живущим в одном STA, синхронизируется самой системой посредством очереди сообщений. СОМ+ идет на встречу реальным предпочтениям программистов, предлагая возможность задавать синхронизацию доступа к объектам декларативным образом. При этом, даже объекты, живущие в МТА или NA, могут быть защищены от параллельного обращения,

♦ Очереди (асинхронная коммуникация)

В СОМ вызовы всех объектов синхронны. Иными словами, поток, сделавший вызов некоторого метода некоторого объекта, продолжает работу только после получения ответа. Исключением является поток в STA, который может выйти из состояния ожидания ответа для обработки вызова, пришедшего извне и принадлежащего к той же цепочке вызовов, что и вызов, ответ на который ожидается. Такая синхронная модель очевидно не сработает при временном выходе из строя сервера, в котором живет вызываемый объект. Решением указанной проблемы является асинхронная коммуникация. Вызов ставится в некоторую очередь вызовов, а вызывающий поток продолжает свою работу. Вызов из очереди извлекается и передается для выполнения серверу тогда, когда он станет доступным.