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



Множественные интерфейсы и имена методов - часть 7


class CarBoatPlane : public ICar, public IPlane { LONG m_cRef; char *m_pTonsOfMemory; CarBoatPlane (void) : m_cRef(0), m_pTonsOfMemory (0) {} public: // IUnknown methods - методы IUnknown STDMETHODIMP QueryInterface(REFIID, void**); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // IVehicle methods - методы IVehicle STDMETHODIMP GetMaxSpeed(long *pMax); // ICar methods - методы ICar STDMETHODIMP Brake(void); // IPlane methods - методы IPlane STDMETHODIMP TakeOff(void);

// define nested class that implements IBoat // определяем вложенный класс, реализующий IBoat struct XBoat : public IBoat { // get back pointer to main object // получаем обратный указатель на главный объект inline CarBoatPlane* This(); LONG m_cBoatRef; // per-interface ref count // счетчик ссылок на каждый интерфейс XBoat(void) : m_cBoatRef(0) {} STDMETHODIMP QueryInterface(REFIID, void**); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); STDMETHODIMP GetMaxSpeed(long *pval); STDMETHODIMP Sink(void); }; XBoat m_xBoat; };

Реализация AddRef и Release из IBoat могут теперь следить за числом ссылок типа IBoat и высвободить ресурсы, когда они больше не нужны:

STDMETHODIMP_(ULONG) CarBoatPlane::XBoat::AddRef() { ULONG res = InterlockedIncrement(&m_cBoatRef); if (res == 1) { // first AddRef - первый AddRef // allocate resource and forward AddRef to object // размещаем ресурсы и пересылаем AddRef на объект This()->m_pTonsOfMemory = new char[4096*4096]; This()->AddRef(); } return res; }

STDMETHODIMP_(ULONG) CarBoatPlane::XBoat::Release() { ULONG res = InterlockedDecrement(&m_cBoatRef); if (res == 0) { // last Release - последний Release // free resource and forward Release to object // освобождаем ресурсы и пересылаем Release на объект delete [] This()->m_pTonsOfMemory; This()->Release(); } return res; }

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


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