lugre_smartptr.h

Go to the documentation of this file.
00001 /*
00002 http://www.opensource.org/licenses/mit-license.php  (MIT-License)
00003 
00004 Copyright (c) 2007 Lugre-Team
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a copy
00007 of this software and associated documentation files (the "Software"), to deal
00008 in the Software without restriction, including without limitation the rights
00009 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00010 copies of the Software, and to permit persons to whom the Software is
00011 furnished to do so, subject to the following conditions:
00012 
00013 The above copyright notice and this permission notice shall be included in
00014 all copies or substantial portions of the Software.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00019 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00020 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00021 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00022 THE SOFTWARE.
00023 */
00024 #ifndef LUGRE_SMARTPTR_H
00025 #define LUGRE_SMARTPTR_H
00026 
00027 #include "lugre_prefix.h"
00028 #include <list>
00029 #include <assert.h>
00030 
00031 
00032 namespace Lugre {
00033 
00034 class cListener;
00035 template<class _T> class cSmartPtr;
00036     
00037 class cListenable { public:
00038              cListenable();
00039     virtual ~cListenable();
00040     void    NotifyAllListeners  (const size_t eventcode = 0,void* param = 0);
00041     void    RegisterListener    (cListener* pListener,void* userdata = 0);
00042     void    UnRegisterListener  (cListener* pListener,void* userdata = 0);
00043     int     CountListeners      () { return mlListener.size(); }
00044     int         iUsageCounter;
00045     bool        bNeedsCompacting; 
00046 
00047     private:
00048     std::list< std::pair< cSmartPtr< cListener > *,void* > >    mlListener;
00049 };
00050 
00052 class cISmartPtr { public:
00053     virtual void    SmartPtr_TargetDestroyed () = 0;
00054 };
00055 
00060 template<class _T> class cSmartPtr : public cListenable, public cISmartPtr { public:
00061     enum { kDefaultTargetDestroyedEventCode = 255 };
00062     size_t  miTargetDestroyedEventCode;
00063         
00064     cSmartPtr(_T* target=0,const size_t iTargetDestroyedEventCode=kDefaultTargetDestroyedEventCode)
00065                             : miTargetDestroyedEventCode(iTargetDestroyedEventCode), target(target) { PROFILE 
00066         if (target) target->RegisterSmartPtr(this); 
00067     }
00068                             
00069     virtual ~cSmartPtr()    { PROFILE 
00070         if (target) target->UnRegisterSmartPtr(this); 
00071         target = 0; 
00072     }
00073     void    SmartPtr_SetTarget (_T* newtarget) { PROFILE
00074         if (target) target->UnRegisterSmartPtr(this);
00075         target = newtarget;
00076         if (target) target->RegisterSmartPtr(this);
00077     }
00078     inline const cSmartPtr<_T>& operator = (cSmartPtr<_T> othersmartptr)    { PROFILE SmartPtr_SetTarget(*othersmartptr);   return *this; }
00079     inline const cSmartPtr<_T>& operator = (_T* newtarget)                  { PROFILE SmartPtr_SetTarget(newtarget);        return *this; }
00080     inline _T* operator * ()            { return target; }
00081     
00084     void    SmartPtr_TargetDestroyed () { PROFILE 
00085         NotifyAllListeners(miTargetDestroyedEventCode); target = 0;   // anything might happen in here...
00086     }
00087     
00088     private:
00089     _T* target; 
00090 };
00091 
00093 class cSmartPointable : public cListenable { public:
00094 
00095     enum { kDefaultDeathEventCode = 255 };
00096     size_t  miDeathEventCode;
00097     
00098     cSmartPointable(const size_t iDeathEventCode=kDefaultDeathEventCode) : miDeathEventCode(iDeathEventCode) {}
00099     virtual ~cSmartPointable() { PROFILE 
00100         ReleaseAllSmartPtr(); 
00101         NotifyAllListeners(miDeathEventCode);
00102     }
00103     void    ReleaseAllSmartPtr  () { PROFILE 
00104         // foreach mlPtr
00105         for (std::list<cISmartPtr*>::iterator itor = mlPtr.begin();itor != mlPtr.end();++itor) {
00106             if (*itor) (*itor)->SmartPtr_TargetDestroyed();  // this causes a notify, anything might happen in here...
00107         }
00108         mlPtr.clear();
00109     }
00110     void    RegisterSmartPtr    (cISmartPtr* ptr) { PROFILE 
00111         assert(ptr); 
00112         mlPtr.push_back(ptr); 
00113     }
00114     void    UnRegisterSmartPtr  (cISmartPtr* ptr) { PROFILE 
00115         assert(ptr); 
00116         for (std::list<cISmartPtr*>::iterator itor = mlPtr.begin();itor != mlPtr.end();++itor) 
00117             if (*itor == ptr)
00118                 *itor = 0;
00119         // warning, do not remove the smartptrs from the list, this would be fatal if it happens during iteration
00120         // warning, memory leak. smartpointers cannot be savely removed during iteration so they are just set to zero. 
00121             // but this is not a big leak and far better than broken iterators (=bug-search-headache)
00122     }
00123     int     CountSmartPtrs      () { return mlPtr.size(); }
00124     
00125     
00126     private:
00127     std::list<cISmartPtr*>  mlPtr;
00128 };
00129     
00130 class cListener : public cSmartPointable { public: // cSmartPointable might also become listenable
00131     cListener() {}
00132     virtual ~cListener() {}
00133     virtual void Listener_Notify (cListenable* pTarget,const size_t eventcode = 0,void* param = 0,void* userdata = 0) = 0;
00134 };
00135 
00136 };
00137 
00138 #endif

Generated on Wed Feb 8 06:00:12 2012 for cpp by  doxygen 1.5.6