00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #ifndef INCLUDED_GC_PTR_HH
00025 #define INCLUDED_GC_PTR_HH
00026 
00027 #ifndef INCLUDED_THREAD_LOCK_HH
00028 #include "Thread/Lock.hh"
00029 #endif
00030 
00031 #ifndef INCLUDED_THREAD_SYNCHRONIZE_HH
00032 #include "Thread/Synchronize.hh"
00033 #endif
00034 
00035 namespace fatalmind {
00036 
00037 
00038 template<class T, class TM> class gc_ptr;
00039 
00040 
00041 
00042 
00043 template<class T, class U>
00044 class Conversion
00045 {
00046         typedef char Small;
00047         class Big {char dummy[2]; };
00048 
00049         static Small Test(U&);
00050         static Big   Test(...);
00051         static T&    MakeT();
00052     public:
00053         enum {exists = sizeof(Test(MakeT())) == sizeof(Small) };
00054 };
00055 
00056 template<class TM>
00057 class usg_cnt_t {
00058         typedef typename TM::FastLock lock_t;
00059         typedef fatalmind::Synchronize<lock_t> sync;
00060     public:
00061         inline usg_cnt_t(): d_cnt(1) {};
00062         inline ~usg_cnt_t() {};
00063 
00064     private:
00065         inline int inc() {sync s(_lk); return ++d_cnt;};
00066         inline int dec() {sync s(_lk); return --d_cnt;};
00067         inline void reset() {sync s(_lk); d_cnt = 1;};
00068 
00069         int d_cnt;
00070         lock_t _lk;
00071 
00072         
00073         
00074         usg_cnt_t(const usg_cnt_t&);
00075 
00076         template<class T, class TM2>
00077         friend
00078         class gc_ptr;
00079 };
00080 
00081 template<class T, class TM>
00082 class gc_ptr_ref {
00083     public:
00084         gc_ptr_ref(T* ptr, usg_cnt_t<TM>* usg) 
00085         : d_ptr(ptr)
00086         , d_usg(usg)
00087         {
00088         }
00089         
00090         typedef usg_cnt_t<TM> usg_cnt;
00091         T* d_ptr;
00092         usg_cnt* d_usg;
00093 };
00094 
00099 
00100 
00101 template<class T, class TM = fatalmind::DefaultThreadedModel>
00102 class gc_ptr {
00103         typedef usg_cnt_t<TM> usg_cnt;
00104     public:
00105         
00106         explicit gc_ptr(T* p=0)
00107         : d_ptr(p)
00108         , d_usg( newUsageCounter(p))
00109         {
00110         };
00111 
00120         void resetFromExisting(T* ptr) 
00121         {
00122             if (d_ptr != ptr) {
00123                 dispose();
00124                 d_ptr = ptr;
00125                 d_usg = ptr;
00126                 d_usg->inc();
00127             }   
00128         }
00129 
00130         inline gc_ptr(const gc_ptr<T, TM>&p) throw()
00131         :   d_ptr(p.get()), d_usg(p.d_usg) 
00132         {
00133             if (d_usg) {
00134                 d_usg->inc();
00135             }
00136         }
00137 
00138         inline gc_ptr(const gc_ptr_ref<T, TM>&p) throw()
00139         :   d_ptr(p.d_ptr), d_usg(p.d_usg) 
00140         {
00141             if (d_usg) {
00142                 d_usg->inc();
00143             }
00144         }
00145 
00146         ~gc_ptr() throw() {
00147             dispose();
00148         }
00149     
00150         inline gc_ptr<T, TM>& operator= (const gc_ptr<T, TM>& p) throw()
00151         {
00152             if (this != &p) {
00153                 dispose();
00154                 d_ptr = p.d_ptr;
00155                 d_usg = p.d_usg;
00156                 if (d_usg) {
00157                     d_usg->inc();
00158                 }
00159             }
00160             return *this;
00161         }
00162 
00163         inline T& operator*() const throw()
00164         {
00165             return *d_ptr;
00166         }
00167         
00168         inline T* operator->() const throw()
00169         {
00170             return d_ptr;
00171         }
00172 
00173         inline T* get() const throw()
00174         {
00175             return d_ptr;
00176         }
00177 
00178         inline bool isNull() const throw()
00179         {
00180             return d_ptr == 0;
00181         }
00182     
00183         void reset(T* ptr= 0) throw()
00184         {
00185             if (d_ptr != ptr) {
00186                 dispose();
00187                 d_ptr = ptr;
00188                 d_usg = newUsageCounter(ptr);
00189             }   
00190         }
00191 
00192         inline bool operator<(const gc_ptr<T>& a) const {
00193             return *d_ptr < *a.d_ptr;
00194         }
00195 
00196         template<class Y>
00197         operator gc_ptr_ref<Y, TM>() throw() {
00198             return gc_ptr_ref<Y, TM>(d_ptr, d_usg);
00199         }
00200 
00201     protected:
00202         T* d_ptr;
00203         usg_cnt* d_usg;
00204 
00205         inline void dispose() throw() {
00206             if (d_usg != 0 && d_usg->dec() == 0) {
00207                 if (!Conversion<T, usg_cnt>::exists) {
00208                     delete d_usg;
00209                 }
00210                 delete d_ptr;
00211             }
00212         }
00213 
00214         
00215         
00216         
00217         
00218         
00219         static inline usg_cnt* newUsageCounter(const T* p) {
00220             return ( (Conversion<T, usg_cnt>::exists ?  
00221                       (usg_cnt*)(p) 
00222                     : (p != 0 ? 
00223                           new usg_cnt()
00224                         : 0))
00225             ) ;
00226         }
00227 };
00228 
00229 } 
00230 
00231 #endif