#pragma once // // a delegate // class Delegate { public: inline Delegate () : m_handlers (NULL) { m_DelegateID [0] = 0; m_MoveFirst = NULL; m_MoveLast = NULL; m_ForEachBreak = false; } inline Delegate (const char * DelegateID) : m_handlers (NULL) { strncpy (m_DelegateID, DelegateID, sizeof(m_DelegateID)); m_MoveFirst = NULL; m_MoveLast = NULL; m_ForEachBreak = false; } inline virtual ~Delegate () { RemoveAll (); } inline virtual void AddDelegateHandler (DelegateHandler * handler) { try { DSingleLock Lock (& ((DMutex &)m_handlers), true); if (! IsExist (handler)) { m_handlers.Add (handler); AdjustPosition (); } else { delete handler; } } catch (...) { } } inline Delegate & operator += (DelegateHandler * handler) { AddDelegateHandler (handler); return *this; } inline virtual void RemoveDelegateHandler (DelegateHandler * handler) { try { RemoveHandler (handler); delete handler; } catch (...) { } } inline Delegate & operator -= (DelegateHandler * handler) { RemoveDelegateHandler (handler); return *this; } inline void operator () (const void * sender, DelegateArgs * arg) { Invoke (sender, arg); } inline virtual void Invoke (const void * sender, DelegateArgs * arg) { int Size = GetSize (); if (Size == 0) return; DSingleLock Lock (& m_handlers.GetMutex (), true); if (Size <= DelegateMaxHandler) { DelegateHandler * arTemp [DelegateMaxHandler]; const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp, DelegateMaxHandler); for (int Index=0; IndexInvoke (sender, arg); } #ifndef _DEBUG catch (...) { Beep (1000, 1000); OnDelegateInvokeFailed (h); } #endif } } else { FixArray arTemp (m_handlers.GetSize ()); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp); for (int Index=0; IndexInvoke (sender, arg); } #ifndef _DEBUG catch (...) { Beep (1000, 1000); OnDelegateInvokeFailed (h); } #endif } } } inline int GetSize () const { const Array * ar = & m_handlers; return ar->GetSize (); } inline bool IsEmpty () const { const Array * ar = & m_handlers; return ar->IsEmpty (); } inline bool IsExist (const DelegateHandler * handler) const { for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { DelegateHandler * curHandler = Iter (); if (curHandler->IsEqual (* handler)) return true; } return false; } inline void RemoveAll () { m_handlers.RemoveAll (); } inline virtual void AddFirst (DelegateHandler * handler) { try { DSingleLock Lock (& ((DMutex &)m_handlers), true); if (! IsExist (handler)) m_handlers.InsertFirst (handler); else delete handler; } catch (...) { } } inline virtual void AddLast (DelegateHandler * handler) { try { DSingleLock Lock (& ((DMutex &)m_handlers), true); if (! IsExist (handler)) m_handlers.InsertLast (handler); else delete handler; } catch (...) { } } template void ForEach (pfnForEach pFunction) { int Size = GetSize (); if (Size == 0) return; DSingleLock Lock (& m_handlers.GetMutex (), true); m_ForEachBreak = false; if (Size <= DelegateMaxHandler) { DelegateHandler * arTemp [DelegateMaxHandler]; // int NbOfElem = m_handlers.CopyTo (arTemp, DelegateMaxHandler); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp, DelegateMaxHandler); for (int Index=0; Index arTemp (m_handlers.GetSize ()); // int NbOfElem = m_handlers.CopyTo (arTemp, DelegateMaxHandler); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp); for (int Index=0; Index void ForEach (pfnForEach pFunction, Parameter para) { int Size = GetSize (); if (Size == 0) return; DSingleLock Lock (& m_handlers.GetMutex (), true); m_ForEachBreak = false; if (Size <= DelegateMaxHandler) { DelegateHandler * arTemp [DelegateMaxHandler]; // int NbOfElem = m_handlers.CopyTo (arTemp, DelegateMaxHandler); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp, DelegateMaxHandler); for (int Index=0; Index arTemp (m_handlers.GetSize ()); // int NbOfElem = m_handlers.CopyTo (arTemp, DelegateMaxHandler); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp); for (int Index=0; Index void ForEach (pfnForEach pFunction, Delegate * SThis) { int Size = GetSize (); if (Size == 0) return; DSingleLock Lock (& m_handlers.GetMutex (), true); m_ForEachBreak = false; if (Size <= DelegateMaxHandler) { DelegateHandler * arTemp [DelegateMaxHandler]; // int NbOfElem = m_handlers.CopyTo (arTemp, DelegateMaxHandler); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp, DelegateMaxHandler); for (int Index=0; Index arTemp (m_handlers.GetSize ()); // int NbOfElem = m_handlers.CopyTo (arTemp, DelegateMaxHandler); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp); for (int Index=0; Index void ForEach (pfnForEach pFunction, Delegate * SThis, Parameter para) { int Size = GetSize (); if (Size == 0) return; DSingleLock Lock (& m_handlers.GetMutex (), true); m_ForEachBreak = false; if (Size <= DelegateMaxHandler) { DelegateHandler * arTemp [DelegateMaxHandler]; // int NbOfElem = m_handlers.CopyTo (arTemp, DelegateMaxHandler); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp, DelegateMaxHandler); for (int Index=0; Index arTemp (m_handlers.GetSize ()); // int NbOfElem = m_handlers.CopyTo (arTemp, DelegateMaxHandler); const Array & ar = m_handlers; int NbOfElem = ar.CopyTo (arTemp); for (int Index=0; Index & toArray) { m_handlers.TransferTo (toArray); return toArray.GetSize (); } inline int TransferFrom (Array & fromArray) { fromArray.TransferTo (m_handlers); return m_handlers.GetSize (); } inline int CopyTo (Array & toArray) const { for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { DelegateHandler * h = Iter (); toArray.Add (h->Clone ()); } return toArray.GetSize (); } inline int CopyTo (Delegate & toDelegate) const { for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { DelegateHandler * h = Iter (); toDelegate.AddDelegateHandler (h->Clone ()); } return toDelegate.GetSize (); } inline int IndexOf (DelegateHandler * h) const { return m_handlers.IndexOf (h); } inline int IndexOf (const char * Name) const { if (! Name) return -1; if (Name[0] == 0) return -1; for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { DelegateHandler * h = Iter (); if (h->m_Name[0] == 0) continue; if (strcmp (h->m_Name, Name) == 0) return Iter.Index (); } return -1; } const DelegateHandler * Find (const char * Name) const { if (! Name) return NULL; if (Name[0] == 0) return NULL; for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { DelegateHandler * h = Iter (); if (h->m_Name[0] == 0) continue; if (strcmp (h->m_Name, Name) == 0) return h; } return NULL; } DelegateHandler * Find (const char * Name) { if (! Name) return NULL; if (Name[0] == 0) return NULL; for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { DelegateHandler * h = Iter (); if (h->m_Name[0] == 0) continue; if (strcmp (h->m_Name, Name) == 0) return h; } return NULL; } template DelegateHandler * Find (const T * This) { if (! This) return NULL; for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { try { ClassDelegateHandler * h = (ClassDelegateHandler * ) Iter (); if (h->GetClassInstance () == This) return h; } catch (...) { } } return NULL; } template const DelegateHandler * Find (const T * This) const { if (! This) return NULL; for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { try { ClassDelegateHandler * h = (ClassDelegateHandler * ) Iter (); if (h->GetClassInstance () == This) return h; } catch (...) { } } return NULL; } template int FindAll (const T * This, Array * pArray) { if (! This) return 0; if (! pArray) return 0; for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { try { ClassDelegateHandler * h = (ClassDelegateHandler * ) Iter (); if (h->GetClassInstance () == This) pArray->Add (h); } catch (...) { } } return pArray->GetSize (); } inline DString GetDelegateID (void) const { return m_DelegateID; } DString ToString (void) const; void MoveToFirst (const DelegateHandler * h) { m_MoveFirst = h; AdjustPosition (); } void MoveLast (const DelegateHandler * h) { m_MoveLast = h; AdjustPosition (); } template void MoveToFirst (const T * This) { const DelegateHandler * h = Find (This); if (h) { m_MoveFirst = h; AdjustPosition (); } } template void MoveToLast (const T * This) { const DelegateHandler * h = Find (This); if (h) { m_MoveLast = h; AdjustPosition (); } } void SetForEachBreak (bool b) { m_ForEachBreak = b; } protected: inline bool RemoveHandler (const DelegateHandler * handler) { for (ExclusiveArrayOfPtr ::Iterator Iter (m_handlers); Iter; Iter++) { DelegateHandler * curHandler = Iter (); if (curHandler->IsEqual (* handler)) { m_handlers.RemoveAt (Iter); return true; } } return false; } inline void AdjustPosition (void) { if (m_handlers.IsEmpty ()) return; if (m_MoveFirst) { DelegateHandler * const nh = (DelegateHandler * const) (m_MoveFirst); int Index = m_handlers.IndexOf (nh); if (Index > 0) m_handlers.Swap (0, Index); } if (m_MoveLast) { DelegateHandler * const nh = (DelegateHandler * const) (m_MoveLast); int Index = m_handlers.IndexOf (nh); if (Index < m_handlers.GetSize ()-1) m_handlers.Swap (0, Index); } } protected: char m_DelegateID [64]; ExclusiveArrayOfPtr m_handlers; const DelegateHandler * m_MoveFirst; const DelegateHandler * m_MoveLast; bool m_ForEachBreak; protected: static const int DelegateMaxHandler = 64; };