struct IDestroyMessageHandler{ virtual void onDestroyMessage(IDestroyMessageHandler *pNotifier) = 0; virtual void register(IDestroyMessageHandler *pRelate) = 0; virtual void unregister(IDestroyMessageHandler *pRelate) = 0;};class CanUseTrigger : public virtual IDestroyMessageHandler,{public: virtual ~CanUseTrigger() { for(std::vector::iterator it = m_vRelateList.begin(); it != m_vRelateList.end(); it++) { (*it)->onDestroyMessage(this); } } virtual void register(IDestroyMessageHandler *pRelate) { std::vector ::iterator it = std::find(m_vRelateList.begin(), m_vRelateList.end(), pRelate); if (it == m_vRelateList.end()) { m_vRelateList.push_back(pRelate); } } virtual void unregister(IDestroyMessageHandler *pRelate) { m_vRelateList.erase(std::remove(m_vRelateList.begin(), m_vRelateList.end(), pRelate), m_vRelateList.end()); } virtual void onDestroyMessage(IDestroyMessageHandler *pNotifier) { IDestroyMessageHandler *pTmp = dynamic_cast (pNotifier); if (pTmp) { unregister(pTmp); } }private: std::vector m_vRelateList;};class TriggerBase : public virtual IDestroyMessageHandler{public: virtual ~TriggerBase() { for (std::vector ::iterator it = m_vRelationships.begin(); it != m_vRelationships.end(); it++) { it->pOther->onDestroyMessage(this); } } virtual void onDestroyMessage(IDestroyMessageHandler *pNotifier) { CanUseTrigger *pTmp = dynamic_cast (pNotifier); if (!pTmp) { return; } m_vRelationships.erase(std::remove(m_vRelationships.begin(), m_vRelationships.end(), Relationship(pTmp)), m_vRelationships.end()); } protected: void regToUser(CanUseTrigger *pUser) { std::vector ::iterator itUser = std::find(m_vRelationships.begin(), m_vRelationships.end(), Relationship(pUser)); if (m_vRelationships.end() != itUser) { ++(itUser->RefCount); } else { m_vRelationships.push_back(Relationship(pUser)); m_vRelationships[m_vRelationships.size() - 1].RefCount++; pUser->register(this); } } void unregFormUser(CanUseTrigger *pUser) { std::vector ::iterator itUser = std::find(m_vRelationships.begin(), m_vRelationships.end(), Relationship(pUser)); if (m_vRelationships.end() != itUser) { --(itUser->RefCount); if(itUser->RefCount < 1) { m_vRelationships.erase(itUser); pUser->unregister(this); } } } struct Relationship { CanUseTrigger *pOther; i32_t RefCount; Relationship(CanUseTrigger *pUser) : pOther(pUser), RefCount(0){} Relationship &operator=(const Relationship &rhs) { pOther = rhs.pOther; RefCount = rhs.RefCount; return *this; } bool operator==(const Relationship &rhs) { return pOther == rhs.pOther; } bool operator==(const CanUseTrigger *rhs) { return pOther == rhs; } }; template struct Channel1Base { typedef struct{} is_member_t; typedef struct{} is_not_member_t; virtual ~Channel1Base(){} virtual void invoke(P p) = 0; virtual bool equal(Channel1Base *pOther) = 0; virtual bool isOwner(CanUseTrigger *pCandidate) = 0; }; template
struct Channel2Base { typedef struct{} is_member_t; typedef struct{} is_not_member_t; virtual ~Channel2Base(){} virtual void invoke(P1 p1, P2 p2) = 0; virtual bool equal(Channel2Base *pOther) = 0; virtual bool isOwner(CanUseTrigger *pCandidate) = 0; }; template struct NakedChannel1 : public Channel1Base { typedef Channel1Base
::is_not_member_t member_spec_t; typedef void (* method_t)(P); NakedChannel1(method_t pMethod) : m_pMethod(pMethod){} ~NakedChannel1(){} virtual void invoke(P p) { if (m_pMethod) { m_pMethod(p); } } virtual bool equal(Channel1Base
*pOther) { NakedChannel1
*pTmp = dynamic_cast
*>(pOther); if (!pTmp) { return false; } return m_pMethod == pTmp->m_pMethod; } virtual bool isOwner(CanUseTrigger *pCandidate) { return false; } method_t m_pMethod; }; template
struct MemberChannel1 : public Channel1Base { typedef Channel1Base
::is_member_t member_spec_t; typedef void (T:: *method_t)(P); MemberChannel1(T *pUser, method_t pMethod) : m_pOwner(pUser), m_pMethod(pMethod){} ~MemberChannel1(){} virtual void invoke(P p) { if (m_pOwner && m_pMethod) { (m_pOwner->* m_pMethod)(p); } } virtual bool equal(Channel1Base
*pOther) { MemberChannel1
*pTmp = dynamic_cast *>(pOther); if(!pTmp) { return false; } return (m_pOwner == pTmp->m_pOwner) && (m_pMethod == pTmp->m_pMethod); } virtual bool isOwner(CanUseTrigger *pCandidate) { return m_pOwner == pCandidate; } T *m_pOwner; method_t m_pMethod; }; template struct NakedChannel2 : public Channel2Base { typedef Channel2Base ::is_not_member_t member_spec_t; typedef void (* method_t)(P1, P2); NakedChannel2(method_t pMethod) : m_pMethod(pMethod){} ~NakedChannel2(){} virtual void invoke(P1 p1, P2 p2) { if (m_pMethod) { m_pMethod(p1, p2); } } virtual bool equal(Channel2Base *pOther) { NakedChannel2 *pTmp = dynamic_cast *>(pOther); if (!pTmp) { return false; } return m_pMethod == pTmp->m_pMethod; } virtual bool isOwner(CanUseTrigger *pCandidate) { return false; } method_t m_pMethod; }; template struct MemberChannel2 : public Channel2Base { typedef Channel2Base ::is_member_t member_spec_t; typedef void (T:: *method_t)(P1, P2); MemberChannel2(T *pUser, method_t pMethod) : m_pOwner(pUser), m_pMethod(pMethod){} ~MemberChannel2(){} virtual void invoke(P1 p1, P2 p2) { if (m_pOwner && m_pMethod) { (m_pOwner->* m_pMethod)(p1, p2); } } virtual bool equal(Channel2Base *pOther) { MemberChannel2 *pTmp = dynamic_cast *>(pOther); if (!pTmp) { return false; } return (m_pOwner == pTmp->m_pOwner) && (m_pMethod == pTmp->m_pMethod); } virtual bool isOwner(CanUseTrigger *pCandidate) { return m_pOwner == pCandidate; } T *m_pOwner; method_t m_pMethod; }; private: std::vector m_vRelationships;};template class Trigger1 : public TriggerBase{public: ~Trigger1() { for (std::vector *>::iterator it = m_vChannels.begin(); it != m_vChannels.end(); it++) { delete (*it); } } virtual void onDestroyMessage(IDestroyMessageHandler *pNotifier) { CanUseTrigger *pTmp = dynamic_cast (pNotifier); if (!pTmp) { return; } for (std::vector *>::iterator it = m_vChannels.begin(); it != m_vChannels.end(); ) { CanUseTrigger *pTmp = dynamic_cast (pNotifier); if (pTmp && (*it)->isOwner(pTmp)) { it = m_vChannels.erase(it); } else { ++it; } } TriggerBase::onDestroyMessage(pNotifier); } void fire(Param p) { for (std::vector *>::iterator it = m_vChannels.begin(); it != m_vChannels.end(); it++) { (*it)->invoke(p); } } void add(void (* pMethod)(Param)) { Channel1Base *pChannel = new NakedChannel1 (pMethod); std::vector *>::iterator it = m_vChannels.begin(); for (; it != m_vChannels.end(); it++) { if ((*it)->equal(pChannel)) { break; } } if (it != m_vChannels.end()) { m_vChannels.push_back(pChannel); } } template void add(TUser *pUser, void (TUser:: *pMethod)(Param)) { //assert(dynamic_cast (pUser)); Channel1Base *pChannel = new MemberChannel1 (pUser, pMethod); std::vector *>::iterator it = m_vChannels.begin(); for (; it != m_vChannels.end(); it++) { if ((*it)->equal(pChannel)) { break; } } if (it == m_vChannels.end()) { m_vChannels.push_back(pChannel); regToUser(pUser); } } void dec(void (* pMethod)(Param)) { NakedChannel1 TempChannel(pMethod); std::vector *>::iterator it = m_vChannels.begin(); for (; it != m_vChannels.end(); it++) { if ((*it)->equal(&TempChannel)) { break; } } if (it != m_vChannels.end()) { m_vChannels.erase(it); } } template void dec(TUser *pUser, void (TUser:: *pMethod)(Param)) { std::assert(dynamic_cast (pUser)); MemberChannel1 TempChannel(pMethod); std::vector *>::iterator it = m_vChannels.begin(); for (; it != m_vChannels.end(); it++) { if ((*it)->equal(&TempChannel)) { break; } } if (it != m_vChannels.end()) { m_vChannels.erase(it); } }private: std::vector *> m_vChannels;};template class Trigger2 : public TriggerBase{public: ~Trigger2() { for (std::vector *>::iterator it = m_vChannels.begin(); it != m_vChannels.end(); it++) { delete (*it); } } virtual void onDestroyMessage(IDestroyMessageHandler *pNotifier) { CanUseTrigger *pTmp = dynamic_cast (pNotifier); if (!pTmp) { return; } for (std::vector *>::iterator it = m_vChannels.begin(); it != m_vChannels.end(); ) { CanUseTrigger *pTmp = dynamic_cast (pNotifier); if (pTmp && (*it)->isOwner(pTmp)) { it = m_vChannels.erase(it); } else { ++it; } } TriggerBase::onDestroyMessage(pNotifier); } void fire(Param1 p1, Param2 p2) { for (std::vector *>::iterator it = m_vChannels.begin(); it != m_vChannels.end(); it++) { (*it)->invoke(p1, p2); } } void add(void (* pMethod)(Param1, Param2)) { Channel2Base *pChannel = new NakedChannel2 (pMethod); std::vector *>::iterator it = m_vChannels.begin(); for (; it != m_vChannels.end(); it++) { if ((*it)->equal(pChannel)) { break; } } if (it == m_vChannels.end()) { m_vChannels.push_back(pChannel); } } template void add(TUser *pUser, void (TUser:: *pMethod)(Param1, Param2)) { //std::assert(dynamic_cast (pUser)); Channel2Base *pChannel = new MemberChannel2 (pUser, pMethod); std::vector *>::iterator it = m_vChannels.begin(); for (; it != m_vChannels.end(); it++) { if ((*it)->equal(pChannel)) { break; } } if (it == m_vChannels.end()) { m_vChannels.push_back(pChannel); regToUser(pUser); } } void dec(void (* pMethod)(Param1, Param2)) { NakedChannel2 TempChannel(pMethod); std::vector *>::iterator it = m_vChannels.begin(); for (; it != m_vChannels.end(); it++) { if ((*it)->equal(&TempChannel)) { break; } } if (it != m_vChannels.end()) { m_vChannels.erase(it); } } template void dec(TUser *pUser, void (TUser:: *pMethod)(Param1, Param2)) { std::assert(dynamic_cast (pUser)); MemberChannel2 TempChannel(pMethod); std::vector *>::iterator it = m_vChannels.begin(); for (; it != m_vChannels.end(); it++) { if ((*it)->equal(&TempChannel)) { break; } } if (it != m_vChannels.end()) { m_vChannels.erase(it); } }private: std::vector *> m_vChannels;};