/* Limb's can only have one Sponsor, but a Sponsor can have multiple Limbs. A Limb can be a Sponsor for another Limb. If a Sponsor dies (gets destructed), so do all of its Limbs. A sponsor that has multiple limbs, does so with multiple inheritance of CAdminSponsor -OR- mulitple containment. Multiple containment is preferred when the sponsor is has a variable number of limbs. */ #ifndef DEBUG #undef markcu #endif #ifdef markcu //#define SHOW_SPONSOR_INFO #endif #if defined (SHOW_SPONSOR_INFO) #include #endif #ifdef SHOW_SPONSOR_INFO class CDebugClass // This is a temporary class for Mark2's debugging purposes. { public: CSimpleArray bstrSponsors; CSimpleArray bstrLimbs; ~CDebugClass() { USES_CONVERSION; int s = bstrSponsors.GetSize(); int l = bstrLimbs.GetSize(); if (s > 0) { printf("Sponsors left over:\n"); for(int i = 0; i < s; ++i) { printf("%s\n", OLE2A(bstrSponsors[i])); } } if (l > 0) { printf("Limbs left over:\n"); for(int i = 0; i < l; ++i) { printf("%s\n", OLE2A(bstrLimbs[i])); } } if (s > 0 || l > 0) DebugBreak(); } }; extern CDebugClass DebugClass; #endif // // The sole purpose of this class is to provide a // connection with the template CAdminSponsor and the class CAdminLimb // class CBaseSponsor { public: virtual void DetachLimb() = 0; }; #ifdef SHOW_SPONSOR_INFO extern int cSponsor; extern int cLimb; #endif template // CAdminLimbObj must derive from CAdminLimb class CAdminSponsor : // CAdminSponsor is to be inherited by the object "sponsoring" life to a Limb object public CBaseSponsor { public: CAdminSponsor() { #ifdef SHOW_SPONSOR_INFO cSponsor++; printf (" Spon %i %s\n", cSponsor, typeid(*this).name()); DebugClass.bstrSponsors.Add(CComBSTR(typeid(*this).name())); #endif m_pCAdminLimbObj = NULL; m_iidInterface = NULL; } virtual ~CAdminSponsor() { // // If there is a limb attached, destroy it now // if (m_pCAdminLimbObj) { m_pCAdminLimbObj->_ForceDestruction(); } #ifdef SHOW_SPONSOR_INFO int i = DebugClass.bstrSponsors.Find(CComBSTR(typeid(*this).name())); if (i == -1) printf("Name not found in array for:\n"); else DebugClass.bstrSponsors.RemoveAt(i); cSponsor--; printf ("~Spon %i %s\n", cSponsor, typeid(*this).name()); #endif } /*------------------------------------------------------------------------- * Make() *------------------------------------------------------------------------- * Purpose: * * Create a new instance of the Sponsor's limb, if it doesn't already * exist. Return the result of interface query in **ppInterface. */ HRESULT Make(const IID& iidInterface, void **ppInterface) { HRESULT hr = S_OK; if (m_iidInterface == NULL) { assert(m_pCAdminLimbObj == NULL); RETURN_FAILED(m_pCAdminLimbObj->CreateInstance(&m_pCAdminLimbObj)); // CreateInstance() is static // // Now attach the newly made limb to this // m_pCAdminLimbObj->SetBaseSponsor(this); } assert(m_pCAdminLimbObj); hr = m_pCAdminLimbObj->QueryInterface(iidInterface, &m_iidInterface); *ppInterface = m_iidInterface; return hr; } virtual void DetachLimb() { m_pCAdminLimbObj = NULL; m_iidInterface = NULL; } CAdminLimbObj* GetLimb() { return m_pCAdminLimbObj; } private: CComObject* m_pCAdminLimbObj; void * m_iidInterface; }; template // Class that is inheriting this one (this enables static downcasting) class CAdminLimb // this must be inherited by the class given as an argument to the CAdminSponsor template { public: CAdminLimb() { #ifdef SHOW_SPONSOR_INFO cLimb++; printf (" Limb %i %s\n", cLimb, typeid(*this).name()); DebugClass.bstrLimbs.Add(CComBSTR(typeid(*this).name())); #endif m_pCBaseSponsor = NULL; } virtual ~CAdminLimb() { DetachFromSponsor(); #ifdef SHOW_SPONSOR_INFO int i = DebugClass.bstrLimbs.Find(CComBSTR(typeid(*this).name())); if (i == -1) printf("Name not found in array for:\n"); else DebugClass.bstrLimbs.RemoveAt(i); cLimb--; printf ("~Limb %i %s\n", cLimb, typeid(*this).name()); #endif } void _ForceDestruction() { DetachFromSponsor(); // // Let remote users know that this object going to be destructed. // Downcast to the interface pointer...looks tricky but it avoids using dynamic_cast // static_cast(this)->AddRef(); CoDisconnectObject(static_cast((static_cast(this))), 0); // CoDisconnectObject() should have brought the ref count to one, so this line should // cause this object to be deleted. static_cast(this)->Release(); } void SetBaseSponsor(CBaseSponsor *pCBaseSponsor) {m_pCBaseSponsor = pCBaseSponsor;} private: void DetachFromSponsor() { if (m_pCBaseSponsor) { m_pCBaseSponsor->DetachLimb(); m_pCBaseSponsor = NULL; } } CBaseSponsor *m_pCBaseSponsor; };