Сущность технологии COM



Двоичная композиция - часть 8


STDMETHODIMP CarClass::CreateInstance(IUnknown *punk0uter, REFIID riid, void **ppv) { // verify that aggregator only requests IUnknown as // initial interface // проверяем, что агрегатор только запрашивает IUnknown как // начальный интерфейс if (pUnkOuter != 0 && riid != IID_IUnknown) return (*ppv = 0), E_INVALIDARG; // create new object/aggregate // создаем новый объект или агрегат Car *р = new Car(pUnkOuter); if (!p) return (*ppv = 0), E_OUTOFMEMORY; // return resultant pointer // возвращаем результирующий указатель p->InternalAddRef(); HRESULT hr = p->InternalQueryInterface(riid, ppv); p->InternalRelease(); return hr; }

Отметим, что здесь используются неделегирующие версии QueryInterface, AddRef и Release. Если создается автономная идентификационная единица, то это, конечно, допустимо. Если же создается агрегат, то необходимо убедиться, что AddRef обработал внутренний, а не внешний объект. Отметим также, что внешний объект в качестве начального интерфейса должен запросить IUnknown. Все это регламентировано Спецификацией СОМ. Если бы внешний объект мог запрашивать произвольный начальный интерфейс, то внутреннему объекту пришлось бы хранить два дублирующих набора указателей vptr: один набор делегировал бы свои реализации QueryInterface, AddRef и Release, а другой — нет. При допущении в качестве начального интерфейса одного IUnknown разработчик объекта может выделить только один vptr, который будет действовать как неделегирующий IUnknown.

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


Содержание  Назад  Вперед