Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 11
На сайте нет зарегистрированных пользователей

Пользователей: 13,364
новичок: eqvufy
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

База данных - рабочее место кассира на Delphi + бд Access
Калькулятор на Delphi с переводом в другую систему исчисления + Блок схемы
Информационная система - продуктовый магазин на Turbo Pascal (База данны...

Оптимизации



Одно из преимуществ использования стандартного интерфейса для создания экземпляров ( instantiation ) состоит в том, что СОМ может обеспечить более эффективную технологию реализации. Рассмотрим следующий код, который создает новый экземпляр класса Chimp :
HRESULT CreateChimp(/* [out] */ IApe * &rpApe)
{
extern const CLSID CLSID_Chimp;
rpApe = 0;
IClassFactory *pcf = 0;
HRESULT hr = CoGetClassObject(CLSID_Chimp, CLSCTX_ALL, 0, IID_IClassFactory, (void**)&pcf);
if (SUCCEEDED(hr))
{
hr = pcf->CreateInstance(0, IID_IApe, (void**)&rpApe);
pcf->Release();
}
return hr;
}



Этот код выполняет одну операцию: создание объекта Chimp . Заметим, что для выполнения одной операции понадобилось три вызова подопераций (suboperations) – CoGetClassObject , CreateInstance , Release . Если сервер загружен как внутрипроцессный, то эти три подоперации не обойдутся слишком дорого. Если, однако, сервер является внепроцессным или внехостовым, то каждая из этих подопераций потребует вызова между процессами клиента и сервера. Хотя СОМ использует очень эффективную передачу IPC/RPC (Interprocess Communication/Remote Procedure Call), каждая из этих подопераций потребует немалых исполнительных затрат. В идеале было бы лучше потребовать, чтобы СОМ перешел на серверный процесс один раз и, находясь там, использовал объект класса для вызова CreateInstance от имени клиента. Если объект класса используется только для реализации IClassFactory , то этот способ будет более эффективным, чем трехшаговый способ, показанный ранее. В СОМ имеется API-функция: CoCreateInstanceEx , относящаяся по своему назначению к той же категории, что CoGetClassObject и IClassFactory::CreateInstance – обеспечивающая создание новых объектов за одно обращение между процессами.
CoCreateInstanceEx дает клиенту возможность задать CLSID для определения, какой объект следует реализовать. В случае успешного выполнения СоСгеаteInstanceEx возвращает один или более указателей интерфейса, которые ссылаются на новый экземпляр заданного класса. При использовании CoCreateInstanceEx клиент никогда не видит промежуточный объект класса, который используется для создания экземпляра объекта. Чтобы клиенты могли вызывать CoCreateInstanceEx , никаких дополнительных функций серверу реализовывать не нужно. С точки зрения сервера все, что необходимо, – это объявить свои объекты классов, как требуется для CoGetClassObject . Реализация CoCreateInstanceEx для нахождения соответствующего объекта класса будет использовать ту же технологию, что и CoGetClassObject . Основное различие заключается в том, что после нахождения объекта CoCreateInstanceEx выполняет дополнительный вызов IClassFactory::CreateInstance , за которым могут последовать один или более вызовов QueryInterface , и все это во время выполнения процесса объекта класса . Можно получить значительную экономию на этапе выполнения, если запрос на активацию закрепить за определенным процессом.
Подобно CoGetClassObject , CoCreateInstanceEx позволяет клиенту задавать желаемые параметры CLSCTX и COSERVERINFO . Кроме того, CoCreateInstanceEx дает клиенту возможность запрашивать более одного указателя интерфейса на вновь создаваемый объект. Это делается путем предоставления клиенту возможности передавать массив структур MULTI_QI , который будет использован для вызова QueryInterface , новому экземпляру во время выполнения серверного процесса:
typedef struct tagMULTI_QI {
// which interface is desired?
// какой интерфейс требуется?
const IID *piid;
// null on input, will contain the pointer on output
// на входе нуль, на выходе будет содержать указатель
[iid_is(piid)] IUnknown *pItf;
// will contain the HRESULT from QueryInterface on output
// на выходе будет содержать HRESULT от QueryInterface
HRESULT hr;
}
MULTI_QI;



Так как клиент может запрашивать более чем один указатель интерфейса на новый объект, он более не нуждается в явном вызове QueryInterface , если ему требуется более чем один тип указателей интерфейса. Поскольку эти вызовы QueryInterface будут сделаны СОМ от имени клиента по время выполнения внутри процесса объекта класса, более не потребуется никаких обменов данными между клиентом и объектом. Отметим, что каждый из указателей интерфейса, возвращенных CoCreateInstanceEx , будет указывать на один и тот же объект. СОМ не поддерживает внутреннего режима создания нескольких экземпляров за одно обращение.
После постижения структуры MULTI_QI понять определение CoCreateInstanceEx уже нетрудно:
HRESULT CoCreateInstanceEx( [in] REFCLSID rclsid,
// what kind of object? – какого сорта объект?
[in] IUnknown *pUnkOuter,
// for aggregation – для агрегирования
[in] DWORD dwClsCtx,
// locality? – размещение?
[in] COSERVERINFO *pcsi,
// host/security info – информация о хосте/безопасности
[in] ULONG cmqi,
// how many interfaces? – сколько интерфейсов?
[out, size_is (cmqi)] MULTI_QI *prgmq
// where to put itfs – куда разместить интерфейсы );



Если все запрошенные интерфейсы доступны в новом объекте, то CoCreateInstanceEx возвращает S_OK . Если хотя бы один (но не все) из запрошенных интерфейсов недоступен, то CoCreateInstanceEx возвратит CO_S_NOTALLINTERFACES , индицируя частичный успех. Затем вызывающий объект должен исследовать индивидуальные HRESULT в каждой структуре MULTI_QI , чтобы определить, какие интерфейсы были доступны, а какие – нет. Если CoCreateInstanceEx не может создать объект или ни один из запрошенных интерфейсов не доступен, то CoCreateInstanceEx возвращает HRESULT с кодом серьезности ошибки SEVERITY_ERROR , который сообщит, почему произошел отказ в операции.
CoCreateInstanceEx чрезвычайно эффективен в случае, когда требуются интерфейсы нескольких типов. Рассмотрим дополнительное определение интерфейса:
[object,uuid(753A8F7C-A7FF-11d0-8C30-0080C73925BA)]
interface IEgghead : IUnknown
{
import «unknwn.idl»;
HRESULT ContemplateNavel(void);
}



Имея такое определение интерфейса, клиент может привязать оба типа указателей к новому шимпанзе за одно обращение:
void CreateChimpEatBananaAndThinkAboutIt(void)
{
// declare and initialize an array of MULTI_QI's
// объявляем и инициализируем массив MULTI_QI
MULTI_QI rgmqi[2] = { { &IID_IApe, 0, 0 }, { &IID_IEgghead, 0, 0 } };
HRESULT hr = CoCreateInstanceEx( CLSID_Chimp,
// make a new chimp – создаем нового шимпанзе
0,
// no aggregation – без агрегирования
CLSCTX_ALL,
// any locality – размещение любое
0,
// no explicit host/security info
// нет явной информации о хосте и безопасности
2,
// asking for two interfaces – запрашиваем 2 интерфейса
rgmqi);
// array of MULTI_QI structs – массив структур
MULTI_QI
if (SUCCEEDED(hr)) {
// hr may be CO_S_NOTALLINTERFACES, so check each result
// hresult может быть равен CO_S_NOTALLINTERFACES,
// поэтому проверяем каждый результат
if (hr == S_OK || SUCCEEDED(rgmqi[0].hr)) {
// it is safe to blindly cast the resultant ptr to the type
// that corresponds to the IID used to request the interface
// безопасно вслепую преобразовать результирующий
// указатель к типу, соответствующему тому IID,
// который использовался при запросе интерфейса
IАре *рАре = reinterpret_cast(rgmqi[0].pItf);
assert(pApe);
HRESULT hr2 = pApe->EatBanana();
assert(SUCCEEDED(hr2));
pApe->Release();
}
if(hr == S_OK || SUCCEEDED(rgmqi[1].hr)) {
IEgghead *peh = reinterpret_cast(rgmqi[1].pItf);
assert(peh);
HRESULT hr2 = peh->ContemplateNavel();
assert(SUCCEEDED(hr2));
peh->Release();
}
} }



Рисунок 3.3 показывает шаги, которые предпринимаются CoCreateInstanceEx для создания нового объекта. Важно отметить, что оба результирующих указателя будут указывать на один и тот же объект. Если нужны два различных объекта, то требуются и два отдельных вызова CoCreateInstanceEx .
Использование СоСrеateInstanceЕх достаточно просто, если нужен только один интерфейс:
HRESULT CreateChimpAndEatBanana(void)
{
// declare and Initialize a MULTI_QI
// определяем и инициализируем MULTI_QI
MULTI_QI mqi = { &IID_IApe, 0, 0 };
HRESULT hr = CoCreateInstanceEx( CLSID_Chimp,
// make a new chimp – создаем нового шимпанзе
0,
// по aggregation – без агрегирования CLSCTX_ALL,
// any locality – любое расположение
0,
// no explicit host/security Info
// нет явной информации о хосте/безопасности
1,
// asking for one interface – запрашиваем один интерфейс
&mqi);
// array of MULTI_QI structs – массив структур
MULTI_QI
if (SUCCEEDED(hr))
{
IApe *pApe = reinterpret_cast(mqi.pItf);
assert(pApe);
// use the new object – используем новый объект
hr = pApe->EatBanana();
// release the Interface pointer
// освобождаем указатель интерфейса
pApe->Release();
}
return hr;
}



Если нужен только один интерфейс и не передается COSERVERINFO , то СОМ предусматривает несколько более удобную версию CoCreateInstanceEx , именуемую CoCreateInstance [1] :
HRESULT CoCreateInstance( [in] REFCLSID rclsid,
// what kind of object? – какой тип объекта?
[in] IUnknown *pUnkOuter,
// for aggregation – для агрегирования
[in] DWORD dwClsCtx,
// locality? – размещение?
[in] REFIID riid,
// what kind of interface – какой вид интерфейса
[out, iid_is(riid)] void **ppv);
// where to put itf – куда разместить интерфейс



Предыдущий пример становится намного проще, если применить CoCreateInstance
HRESULT CreateChimpAndEatBanana(void)
{
IАре *рАре = 0;
HRESULT hr = CoCreateInstance( CLSID_Chimp,
// make a new chimp – создаем нового шимпанзе
0,
// по aggregation – без агрегирования
CLSCTX_ALL,
// any locality – любое расположение
IID_IApe,
// what kind of itf – какой вид интерфейса
(void**)&pApe);
// where to put iff – куда поместить интерфейс
if (SUCCEEDED(hr)) {
assert(pApe);
// use the new object используем новый объект
hr = pApe->EatBanana();
// release the interface pointer
// освобождаем указатель интерфейса
pApe->Release();
}
return hr;
}



Оба предыдущих примера функционально эквивалентны. В сущности, реализация CoCreateInstance просто осуществляет внутренний вызов CoCreateInstanceEx :
// pseudo-code for implementation of CoCreateInstance API
// псевдокод для реализации API-функции
CoCreateInstance HRESULT
CoCreateInstance(REFCLSID rclsid, IUnknown *pUnkOuter, DWORD dwCtsCtx, REFIID riid, void **ppv)
{
MULTI_QI rgmqi[] = { &riid, 0, 0 };
HRESULT hr = CoCreateInstanceEx(rclsid, pUnkOuter, dwClsCtx, 0, 1, rgmqi);
*ppv = rgmqi[0].pItf;
return hr;
}



Хотя возможно выполнить запрос на удаленную активацию с использованием CoCreateInstance , отсутствие параметра COSERVERINFO не позволяет вызывающему объекту задать явное имя хоста. Вместо этого вызов CoCreateInstance и задание только флага CLSCTX_REMOTE_SERVER предписывает SCM использовать конфигурационную информацию каждого CLSID для выбора хост-машины, которая будет использоваться для активации объекта.
Рисунок 3.4 показывает, как параметры CoCreateInstanceEx преобразуются в параметры CoGetClassObject и IClassFactory::CreateInstance . Вопреки распространенному заблуждению, CoCreateInstanceEx не осуществляет внутренний вызов CoGetClassObject . Хотя между двумя этими методиками нет логических различий, реализация CoCreateInstanceEx будет более эффективной при создании одного экземпляра, так как в этом случае не будет лишних вызовов клиент-сервер, которые могли бы понадобиться, если бы была использована CoGetClassObject . Если, однако, будет создаваться большое число экземпляров, то клиент может кэшировать указатель объекта класса и просто вызвать IClassFactory::CreateInstance несколько раз. Поскольку IClassFactory::CreateInstance является всего лишь вызовом метода и не идет через SCM, он отчасти быстрее, чем вызов CoCreateInstanceEx . Порог, за которым становится более эффективным кэшировать объект класса и обходить CoCreateInstanceEx , будет изменяться в зависимости от эффективности IPC и RPC на используемых хост-машинах и сети.
Опубликовал Kest July 13 2009 09:59:16 · 0 Комментариев · 8194 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
mmmJlabel
C++ Builder в за...
База Allsubmitter...
Работа с базами д...
Простой пример ка...
Панель Наша Кнопка
WinAmp
Прграммирование в...
DiZsubmit
Моделирование дви...
Crypt32
Создание Web-сайт...
C# Учебный курс
PDF
Socoban
Xrumer 4 Platinum...
Синтаксический ан...
Язык программиров...
Dealer
Ics

Топ загрузок
Приложение Клие... 100774
Delphi 7 Enterp... 97832
Converter AMR<-... 20268
GPSS World Stud... 17014
Borland C++Buil... 14191
Borland Delphi ... 10290
Turbo Pascal fo... 7373
Калькулятор [Ис... 5984
Visual Studio 2... 5207
Microsoft SQL S... 3661
Случайные статьи
Проектирование гра...
14.7. Дополнительн...
4.5. РЕШЕНИЕ: СПЕЦ...
Таблица замыканий
Ваша цель — опреде...
1. CSNW может испо...
ЦЕЛЬ: ИСПОЛЬЗОВАН...
Вывести все 3х зна...
Почему так дорого?
4.2. АНТИПАТТЕРН: ...
Задача. Матрица
Программа считывае...
4.3.2. Комбинаци...
Модуль System
Вы можете сразу от...
Каковы значения ад...
Заполнить квадрат NxN
Программирование с...
Представление дере...
Сигареты оптом: ка...
Vulkan Original
Выполнение агрегир...
Программирование а...
Рассчет машинного ...
Поле-шаблон
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?