Сущность технологии СОМ. Библиотека программиста
Добавить в закладки К обложке
- Предисловие Чарли Киндела - Страница 1
- Предисловие Грэйди Буча - Страница 4
- От автора - Страница 5
- Благодарности - Страница 7
- От издательства - Страница 9
- Глава 1. СОМ как улучшенный C++ - Страница 10
- Распространение программного обеспечения и язык С++ - Страница 11
- Динамическая компоновка и С++ - Страница 12
- C++ и мобильность - Страница 13
- Инкапсуляция и С++ - Страница 14
- Отделение интерфейса от реализации - Страница 17
- Абстрактные базы как двоичные интерфейсы - Страница 19
- Полиморфизм на этапе выполнения - Страница 23
- Расширяемость объекта - Страница 25
- Управление ресурсами - Страница 28
- Где мы находимся? - Страница 30
- Глава 2. Интерфейсы - Страница 31
- Снова об интерфейсах и реализациях - Страница 32
- IDL - Страница 33
- Методы и их результаты - Страница 35
- Интерфейсы и IDL - Страница 37
- Интерфейс IUnknown - Страница 39
- Управление ресурсами и IUnknown - Страница 42
- Приведение типов и IUnknown - Страница 45
- Реализация IUnknown - Страница 47
- Использование указателей интерфейса СОМ - Страница 50
- Оптимизация QueryInterface - Страница 52
- Типы данных - Страница 55
- Атрибуты и свойства - Страница 61
- Исключения - Страница 62
- Где мы находимся? - Страница 65
- Глава 3. Классы - Страница 66
- Снова об интерфейсе и реализации - Страница 67
- Объекты классов - Страница 69
- Активация - Страница 71
- Использование SCM - Страница 73
- Классы и серверы - Страница 76
- Обобщения - Страница 81
- Оптимизации - Страница 83
- Снова интерфейс и реализация - Страница 86
- Моникеры и композиция - Страница 89
- Моникеры и сохраняемость - Страница 91
- Время жизни сервера - Страница 93
- Классы и IDL - Страница 95
- Эмуляция классов - Страница 97
- Категории компонентов - Страница 98
- Где мы находимся? - Страница 102
- Глава 4. Объекты - Страница 103
- Снова IUnknown - Страница 104
- QueryInterface симметрична - Страница 105
- QueryInterface транзитивна - Страница 106
- QueryInterface рефлективна - Страница 107
- Объекты имеют статический тип - Страница 108
- Единственность и идентификация - Страница 110
- QueryInterface и IUnknown - Страница 111
- Множественные интерфейсы и имена методов - Страница 113
- Динамическая композиция - Страница 118
- Двоичная композиция - Страница 122
- Включение - Страница 128
- Где мы находимся? - Страница 129
- Глава 5. Апартаменты - Страница 130
- Снова интерфейс и реализация - Страница 131
- Объекты, интерфейсы и апартаменты - Страница 134
- Межапартаментный доступ - Страница 136
- Вспомогательные средства для внутрипроцессного маршалинга - Страница 141
- Архитектура стандартного маршалинга - Страница 144
- Реализация интерфейсных маршалеров - Страница 148
- Стандартный маршалинг, потоки и протоколы - Страница 150
- Управление жизненным циклом и маршалинг - Страница 154
- Специальный маршалинг - Страница 159
- Маршалер свободной поточной обработки (FreeThreaded Marshaler) - Страница 162
- Где мы находимся? - Страница 168
- Глава 6. Приложения - Страница 169
- Подводные камни внутрипроцессной активации - Страница 170
- Активация и SCM - Страница 171
- Снова о времени жизни сервера - Страница 174
- Снова о времени жизни сервера - Страница 178
- Идентификаторы приложений - Страница 182
- COM и защита - Страница 185
- Программируемая защита - Страница 191
- Контроль доступа - Страница 196
- Управление маркерами - Страница 200
- Где мы находимся? - Страница 204
- Разное - Страница 205
- Основы указателей - Страница 206
- Указатели и память - Страница 208
- Массивы - Страница 213
- Управление потоками данных - Страница 221
- Динамический вызов в сравнении со статическим - Страница 224
- Двунаправленные интерфейсные контракты - Страница 227
- Совмещение имен в IDL - Страница 233
- Асинхронные методы - Страница 236
- Где мы находимся? - Страница 237
- Проиложение А. Эволюция объектов - Страница 238
- Приложение Б. Избранный код - Страница 242
Управление потоками данных
Отметим, что в предыдущих примерах использования массивов, в том числе типа SAFEARRAY , вопрос о том, какое количество данных будет передано в ORPC-сообщении, решал отправитель данных. Рассмотрим следующее простое определение метода на IDL:
HRESULT Sum([in] long cElems, [in, size_is(cElems)] double *prgd, [out, retval] double *pResult);
Если бы вызывающая программа должна была запустить этот метод следующим образом:
double rgd[1024 * 1024 * 16];
HRESULT hr = p->Sum(sizeof(rgd)/sizeof(*rgd), rgd);
то размер результирующего ответного сообщения ORPC-запроса был бы не меньше 128 Мбайт. Хотя лежащий в основе RPC-протокол вполне в состоянии разбивать большие сообщения на несколько сетевых пакетов, при использовании больших массивов все же возникают некоторые проблемы. Одна очевидная проблема состоит в том, что вызывающая программа должна иметь свыше 128 Мбайт доступной памяти сверх той, которая занята существующим массивом. Дублирующий буфер необходим интерфейсному заместителю для создания ответного ORPC-сообщения, в которое в конечном счете будет скопирован этот массив. Подобная проблема заключается в том, что процесс объекта также должен иметь больше 128 Мбайт доступной памяти для реконструирования полученных RPC-пакетов в единое сообщение ORPC. Если бы массив использовал атрибут [length_is], то следовало бы выделить еще 128 Мбайт, чтобы скопировать этот массив в память для передачи его методу. Эта проблема относится к параметрам как типа [in], так и [out]. В любом случае отправитель массива может иметь достаточное буферное пространство для создания OPRC-сообщения, а получатель массива – нет. Данная проблема является результатом того, что получатели не имеют механизма для управления потоками на уровне приложений.
Более сложная проблема с приведенным выше определением метода связана со временем ожидания (latency). Семантика ORPC-запроса требует, чтобы на уровне RPC/ORPC полное ORPC-сообшение реконструировалось до вызова метода объекта. Это означает, что объект не может начать обработку имеющихся данных, пока не получен последний пакет. Когда общее время передачи большого массива довольно велико, объект будет оставаться незанятым в течение значительного промежутка времени, ожидая получения последнего пакета. Возможно, что в течение этого времени ожидания многие элементы уже успешно прибыли в адресное пространство объекта; тем не менее, семантика вызова метода в СОМ требует, чтобы к началу текущего вызова присутствовали все элементы. Та же проблема возникает, когда массивы передаются как параметры с атрибутом [out], так как клиент не может начать обработку тех частичных результатов операции, которые, возможно, уже получены к этому моменту.
Для решения проблем, связанных с передачей больших массивов в качестве параметров метода, в СОМ имеется стандартная идиома разработки интерфейсов, позволяющая получателю данных явно осуществлять управление потоками элементов массива. Эта идиома основана на передаче вместо фактических массивов специального интерфейсного указателя СОМ. Этот специальный интерфейсный указатель, называемый нумератором (enumerator), позволяет извлекать элементы из отправителя со скоростью, подходящей для получателя. Чтобы применить эту идиому к приведенному выше определению метода, понадобится следующее определение интерфейса:
interface IEnumDouble : Unknown {
// pull a chunk of elements from the sender
// извлекаем порцию данных из отправителя
HRESULT Next([in] ULONG cElems, [out, size_is(cElems), length_is(*pcFetched)] double *prgElems, [out] ULONG *pcFetched);
// advance cursor past cElems elements
// переставляем курсор после элементов cElems
HRESULT Skip([in] cElems);
// reset cursor to first element
// возвращаем курсор на первый элемент
HRESULT Reset(void);
// duplicate enumerator's current cursor
// копируем текущий курсор нумератора
HRESULT Clone([out] IEnumDouble **pped);
}
Важно отметить, что интерфейс IEnum моделирует только курсор, а отнюдь не текущий массив. Имея такое определение интерфейса, исходное определение метода IDL:
HRESULT Sum([in] long cElems, [in, size_is(cElems)] double *prgd, [out, retval] double *pResult);
преобразуется следующим образом:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253