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

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

Жанры

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

// signal other thread that ptr is now available

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

// теперь доступен

SetEvent (g_heventWritten); return hr; }

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

HRESULT ReadPtrFromGlobalVariable(IRacer * &rpRacer) {

// where to write the marshaled ptr

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

extern IStream *g_pStmPtr;

// thread synchronization for read/write

// синхронизация потока для чтения/записи extern

HANDLE g_heventWritten;

// wait for other thread to signal that ptr is available

// ожидаем

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

// указатель доступен

WaitForSingleObject(g_heventWritten, INFINITE);

// read marshaled object reference from global variable

// читаем маршалированную объектную ссылку из глобальной переменной

HRESULT hr = CoGetInterfaceAndReleaseStream( g_pStmPtr, IID_IRacer. (void**) &rpRacer);

// MSHLFLAGS_NORMAL means no more unmarshals are legal

// MSHLFLAGS_NORMAL означает, что больше не может быть

// извлечено никаких демаршалированных указателей

g_pStmPtr = 0;

return hr;

}

Данный код требуется при передаче указателя от одного апартамента к другому [1] . Отметим, что при передаче указателя от потока, выполняющегося в МТА или RTA, к другому потоку, выполняющемуся в том же апартаменте, не требуется никаких вызовов маршалинга. Тем не менее, обычной практикой для программы записи (writer) интерфейсного указателя является вызов AddRef до передачи копии в поток программы считывания (reader). Когда поток читающей программы выполняется с использованием указателя, ему, конечно, необходимо будет вызвать Release .

1 Может показаться странным, что глобальная переменная является интерфейсным указателем, который инициализирован в апартаменте программы записи, а используется из апартамента программы считывания. Об этой противоречивости упоминается в документации по CoMarshalInterThreadInterfaceInStream, где формулируется, что к результирующему интерфейсному указателю IStream можно обратиться из любого апартамента в процессе.

Отметим, что в приведенном коде программа считывания устанавливает в нуль глобальную переменную g_pStmPtr после демаршалинга. Это сделано потому, что объектная ссылка была маршалирована с флагом MSHLFLAGS_NORMAL и может быть демаршалирована только один раз. Во многих сценариях это не является проблемой. В некоторых других сценариях, однако, желательно маршалировать указатель из одного потока и иметь несколько рабочих потоков, в которых можно демаршалировать интерфейсный указатель по мере необходимости. Если все рабочие потоки выполняются в МТА, то это не является проблемой, поскольку нужно выполнить демаршалинг только в одном потоке – от имени всех потоков, выполняющихся в МТА. Если, однако, рабочие потоки выполняются в произвольных апартаментах, то этот подход не сработает, поскольку тогда придется независимо демаршалировать объектную ссылку в каждом рабочем потоке. Большинство разработчиков в этом случае обращаются к флагу MSHLFLAGS_TABLESTRONG, надеясь на однократный маршалинг и столько демаршалингов, сколько необходимо (по одному разу на апартамент). К сожалению, табличный маршалинг (в отличие от обычного маршалинга) не поддерживается в случае, если исходный указатель является заместителем, что случается часто, особенно в распределенных приложениях. Для разрешения этой проблемы в выпуске СОМ Service Pack 3 под Windows NT 4.0 вводится Глобальная интерфейсная таблипа (Global Interface Table – GIT).

GIT является оптимизацией CoMarshalInterface / CoUnmarshalInterface,

которая допускает обращение к интерфейсным указателям из всех апартаментов процесса. Внутри СОМ реализуется одна GIT на процесс. GIT содержит маршалированные интерфейсные указатели, которые могут быть эффективно демаршалированы несколько раз внутри одного и того же процесса. Это семантически эквивалентно использованию табличного маршалинга, однако GIT можно использовать как для объектов, так и для заместителей. GIT выставляет интерфейс IGlobalInterfaceTable:

[uuid(00000146-0000-0000-C000-000000000046), object, local ]

interface IGlobalInterfaceTable : IUnknown {

// marshal an Interface into the GIT

// маршалируем интерфейс в GIT

HRESULT RegisterInterfaceInGlobal ( [in, iid_is(riid)] IUnknown *pItf, [in] REFIID riid, [out] DWORD *pdwCookie);

// destroy the marshaled object reference

// уничтожаем маршалированную объектную ссылку

HRESULT RevokeInterfaceFromGlobal ( [in] DWORD dwCookle);

// unmarshal an interface from the GIT

// демаршалируем интерфейс из GIT

HRESULT GetInterfaceFromGlobal ( [in] DWORD dwCookie, [in] REFIID riid, [out, iid_is(riid)] void **ppv); }

Клиенты получают доступ к GIT для своего процесса, вызывая CocreateInstance с использованием класса CLSID_StdGlobalInterfaceTable. Каждый вызов CoCreateInstance с применением этого CLSID возвращает указатель на одну и ту же GIT в процессе. Так же как к интерфейсу IStream, возвращенному CoMarshalInterThreadInterfaceInStream, к интерфейсным указателям на GIT можно обратиться из любого апартамента без обязательного маршалинга.

Для того чтобы сделать интерфейсный указатель доступным для всех апартаментов процесса, апартамент, содержащий этот интерфейсный указатель, должен зарегистрировать его в GIT путем вызова метода RegisterInterfaceInGlobal. GIT вернет вызывающей программе DWORD, который представляет глобальный указатель для всех апартаментов процесса. Этот DWORD может быть использован из любого апартамента процесса для демаршалинга нового заместителя путем вызова метода GetInterfaceFromGlobal. Этот же DWORD можно использовать для повторного демаршалинга заместителей до тех пор, пока вызов RevokeInterfaceFromGlobal не объявит глобальный интерфейсный указатель недействительным. Приложения, использующие эту глобальную интерфейсную таблицу (GIT ), обычно связывают один интерфейсный указатель на весь процесс при запуске:

IGlobalInterfaceTable *g_pGIT = 0; HRESULT Init0nce(void) {

assert(g_pGIT == 0);

return CoCreateInstance(CLSID_StdGlobalInterfaceTable, 0, CLSCDX_INPROC_5ERVER, IID_IGlobalInterfaceTable, (void**)&g_pGIT);

}

Когда глобальная интерфейсная таблица является доступной, передача интерфейсного указателя в другой апартамент сводится к простой регистрации указателя в глобальной интерфейсной таблице:

HRESULT WritePtrToGlobalVariable(IRacer *pRacer) {

// where to write the marshaled ptr

// куда записывать маршалированный указатель extern

DWORD g_dwCookie;

// thread synchronization

// синхронизация потока extern HANDLE g_heventWritten;

// write marshaled object reference to global variable

// записываем маршалированную объектную ссыпку в глобальную переменную

HRESULT hr = g_pGIT->RegisterInterfaceInGlobal( pRacer, IID_IRacer, &g_dwCookie);

// signal other thread that ptr is now available

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

Лишняя дочь

Nata Zzika
Любовные романы:
любовно-фантастические романы
8.22
рейтинг книги
Лишняя дочь

Маверик

Астахов Евгений Евгеньевич
4. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Маверик

Мужчина моей судьбы

Ардова Алиса
2. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.03
рейтинг книги
Мужчина моей судьбы

Развод, который ты запомнишь

Рид Тала
1. Развод
Любовные романы:
остросюжетные любовные романы
короткие любовные романы
5.00
рейтинг книги
Развод, который ты запомнишь

Кодекс Охотника. Книга XIV

Винокуров Юрий
14. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XIV

Столкновение

Хабра Бал
1. Вне льда
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Столкновение

Черный маг императора

Герда Александр
1. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора

Кодекс Крови. Книга V

Борзых М.
5. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга V

Любимая учительница

Зайцева Мария
1. совершенная любовь
Любовные романы:
современные любовные романы
эро литература
8.73
рейтинг книги
Любимая учительница

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

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

Боярышня Дуняша 2

Меллер Юлия Викторовна
2. Боярышня
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Боярышня Дуняша 2

Убивать чтобы жить 9

Бор Жорж
9. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 9

Новый Рал 7

Северный Лис
7. Рал!
Фантастика:
попаданцы
5.00
рейтинг книги
Новый Рал 7

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

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