Чтение онлайн

на главную - закладки

Жанры

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

HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);

Для входа во вновь соаданный STA вызывающий объект должен выставить флаг COINIT_APARTMENTTHREADED:

HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);

Каждый поток в процессе, который вызывает CoInitializeEx с применением COINIT_MULTITHREADED, выполняется в том же самом апартаменте. Каждый поток, который вызывает CoInitiаlizeEx с применением COINIT_APARTMENTTHREADED, выполняется в отдельном апартаменте, в который не могут входить никакие другие потоки. CoInitialize – это традиционная подпрограмма, которая просто вызывает CoInitializeEx

с флагом COINIT_APARTMENTTHREADED. Olelnitialize сначала вызывает CoInitialize, а затем инициализирует несколько подсистем из OLE-приложений, таких как OLE Drag and Drop и OLE Clipboard. Если не предполагается использовать эти службы более высокого уровня, то в общем случае предпочтительнее использовать CoInitialize или CoInitializeEx.

Каждая из этих трех API-функций может быть вызвана больше одного раза на поток. Первый вызов каждого потока возвратит S_ОК. Последующие вызовы просто повторно войдут в тот же апартамент и возвратят S_FALSE. На каждый успешный вызов CoInitialize или CoInitializeEx из того же потока нужно вызвать CoUninitialize. На каждый успешный вызов OleInitialize из того же потока нужно вызвать OleUninitialize. Эти подпрограммы деинициализации (uninitialization) имеют очень простые сигнатуры:

void CoUninitialize(void);

void OleUninitialize(void);

Если все эти подпрограммы перед прекращением потока или процесса не вызваны, это может задержать восстановление ресурсов. Когда поток входит в апартамент, недопустимо изменять типы апартамента с использованием CoInitiаlizeEx. При попытках сделать это HRESULT будет содержать RPC_E_CHANGED_MODE. Однако, если поток полностью покинул апартамент посредством CoUninitialize, он может войти в другой апартамент путем повторного вызова CoInitializeEx.

Объекты, интерфейсы и апартаменты

Клиенты хотят вызывать методы объектов. Объекты просто хотят выставлять свои методы для клиентов. Тот факт, что объект может иметь ограничения на параллелизм (concurrency constraints), отличные от тех, которые привносятся клиентским апартаментом, является элементом реализации, о котором клиент не должен знать. Кроме того, если разработчик объекта сочтет нужным развернуть реализацию объекта только на малом количестве хост-машин, которое не содержит той хост-машины, где находится программа клиента, то это также является деталью реализации, о которой клиент не должен знать. В любом случае, однако, объект должен находиться в апартаменте, отличном от апартамента клиента.

С точки зрения программирования, членство в апартаменте является атрибутом интерфейсного указателя, а не атрибутом объекта. Когда интерфейсный указатель возвращается после вызова API-функции СОМ или после вызова метода, то поток, осуществивший вызов API-функции или метода, определяет, к какому апартаменту принадлежит результирующий интерфейсный указатель. Если вызов возвращает указатель на текущий объект, то объект сам расположен в апартаменте вызывающего потока. Часто объект не может находиться в вызывающем апартаменте: или потому, что объект уже существует и другом процессе или на другой хост-машине, или потому, что требования параллелизма, присущие этому объекту, несовместимы с клиентским апартаментом. В этих случаях клиент получает указатель на заместитель (proxy).

В СОМ заместителем называется объект, семантически идентичный объекту в другом апартаменте. По смыслу заместитель представляет собой точную копию объекта в другом апартаменте. Заместитель выставляет тот же набор интерфейсов, что и представляемый им объект, однако реализация заместителем каждого из интерфейсных методов просто переадресовывает вызовы на объект, обеспечивая тем самым то, что методы объекта всегда выполняются в его апартаменте. Любой интерфейсный указатель, получаемый клиентом от вызова API-функции или вызова метода, является легальным для всех потоков в апартаменте вызывающего объекта независимо от того, указывает он на объект или на заместитель.

Разработчики объектов выбирают типы апартаментов, в которых могут выполняться их объекты. В главе 6 будет рассмотрено, что внепроцессные серверы явно задают тип своих апартаментов посредством вызова CoInitializeEx с соответствующим параметром. Для внутрипроцессных серверов необходим другой подход, так как CoInitializeEx уже вызывалась клиентом во время создания объекта. Для того чтобы внутрипроцессные

серверы могли контролировать тип своих апартаментов, в СОМ каждому CLSID разрешается задавать свою собственную потоковую модель (threading model), которая объявляется в локальном реестре с использованием переменной под названием ThreadingModel:

[HKCR\CLSID\ {96556310-D779-11d0-8C4F-0080C73925BA}\InprocServer32]

@="C:\racer.dll"

ThreadingModel="Free"

Каждый CLSID в DLL может иметь индивидуальную ThreadingModel. Под Windows NT 4.0 СОМ допускает четыре возможных значения ThreadingModel для CLSID . Значение ThreadingModel="Both" указывает на то, что класс может выполняться как в МТА, так и в STA. Значение ThreadingModel="Free" указывает, что класс может выполняться только в МТА. Значение ThreadingModel="Apartment" указывает, что класс может выполняться только в STA. Отсутствие ThreadingModel означает, что класс может выполняться только в главном STA. Главный STA определяется как первый STA, который должен быть инициализирован в процессе.

Если апартамент клиента совместим с моделью организации поточной обработки идентификатора класса CLSID , то все запросы на внутрипроцессную активацию для этого CLSID будут обрабатывать объект непосредственно в апартаменте клиента. Это, безусловно, наиболее эффективный сценарий, так как не требуется никаких промежуточных заместителей [1] . Если же апартамент клиента несовместим с моделью организации поточной обработки, указанной в CLSID, то запросы на внутрипроцесспую активацию для таких CLSID будут приводить к скрытому созданию объекта в отдельном апартаменте, а клиенту будет возвращен заместитель. В случае, когда STA– клиенты активируют классы с ThreadingModel="Free", объект класса (и последующие его экземпляры) будут выполняться в МТА. В случае, когда MTA–клиенты активируют классы с ThreadingModel="Apartment", объект класса (и последующие его экземпляры) будут выполняться в STA , созданном СОМ. В случае, когда клиенты любого типа активируют классы на основе главного STA, объект класса (и последующие его экземпляры) будут выполняться в главном STA процесса. Если же клиент окажется потоком главного STA, то будет осуществлен прямой доступ к объекту. В противном случае клиенту будет возвращен заместитель. Если в процессе нет ни одного STA (то есть если ни один поток не вызвал CoInitiаlizeEx с флагом COINIT_APARTMENTTHREADED), тогда СОМ создаст новый STA с тем, чтобы он стал главным STA для процесса.

1 Стоимость выполнения вызова метода из другого апартамента из-за непроизводительных издержек по переключению потоков может быть в тысячи раз выше, чем в случае, когда метод вызывается внутри апартамента.

Разработчики классов, не предусматривающие модель организации поточной обработки для своих классов, могут большей частью игнорировать проблемы, связанные с потоками, так как доступ к их библиотекам DLL будет осуществляться только из одного потока, а именно из главного STA–потока. Те разработчики, которые предусматривают для своих классов поддержку любой явной модели организации поточной обработки, косвенно свидетельствуют, что каждый из множественных апартаментов в процессе (который может быть многопоточным) может содержать экземпляры класса. Поэтому разработчик должен защитить любые ресурсы, которые совместно используются более чем одним экземпляром класса, от параллельного доступа. Это означает, что все глобальные и статические переменные должны быть защищены с помощью соответствующего примитива синхронизации потоков. Для внутрипроцессного сервера СОМ глобальный счетчик блокировок, отслеживающий время жизни сервера, должен быть защищен с помощью InterlockedIncrement / InterlockedDecrement, как показано в главе 3. Любое другое специфическое для сервера состояние также должно быть защищено.

Поделиться:
Популярные книги

Барон меняет правила

Ренгач Евгений
2. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон меняет правила

Чехов. Книга 2

Гоблин (MeXXanik)
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Чехов. Книга 2

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь

Инквизитор Тьмы 2

Шмаков Алексей Семенович
2. Инквизитор Тьмы
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Инквизитор Тьмы 2

Огромный. Злой. Зеленый

Новикова Татьяна О.
1. Большой. Зеленый... ОРК
Любовные романы:
любовно-фантастические романы
5.40
рейтинг книги
Огромный. Злой. Зеленый

Истребитель. Ас из будущего

Корчевский Юрий Григорьевич
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.25
рейтинг книги
Истребитель. Ас из будущего

Купец IV ранга

Вяч Павел
4. Купец
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Купец IV ранга

Боярышня Евдокия

Меллер Юлия Викторовна
3. Боярышня
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Боярышня Евдокия

Боги, пиво и дурак. Том 4

Горина Юлия Николаевна
4. Боги, пиво и дурак
Фантастика:
фэнтези
героическая фантастика
попаданцы
5.00
рейтинг книги
Боги, пиво и дурак. Том 4

Адвокат империи

Карелин Сергей Витальевич
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Адвокат империи

Я тебя не отпускал

Рам Янка
2. Черкасовы-Ольховские
Любовные романы:
современные любовные романы
6.55
рейтинг книги
Я тебя не отпускал

Черный Маг Императора 8

Герда Александр
8. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 8

Сирота

Шмаков Алексей Семенович
1. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Сирота

Прометей: повелитель стали

Рави Ивар
3. Прометей
Фантастика:
фэнтези
7.05
рейтинг книги
Прометей: повелитель стали