00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 #ifndef SINGLETON_INC_
00056 #define SINGLETON_INC_
00057 
00058 #include <base/Threads>
00059 #include <algorithm>
00060 #include <stdexcept>
00061 #include <cassert>
00062 #include <cstdlib>
00063 #include <new>
00064 
00065 namespace base
00066 {
00067     namespace Private
00068     {
00069 
00070 
00071 
00072 
00073 
00074         class LifetimeTracker
00075         {
00076         public:
00077             LifetimeTracker(unsigned int x) : longevity_(x) 
00078             {}
00079             
00080             virtual ~LifetimeTracker() = 0;
00081             
00082             static bool Compare(const LifetimeTracker* lhs,
00083                 const LifetimeTracker* rhs)
00084             {
00085                 return rhs->longevity_ > lhs->longevity_;
00086             }
00087             
00088         private:
00089             unsigned int longevity_;
00090         };
00091         
00092         
00093         inline LifetimeTracker::~LifetimeTracker() {} 
00094         
00095         
00096         typedef LifetimeTracker** TrackerArray;
00097         extern TrackerArray pTrackerArray;
00098         extern unsigned int elements;
00099 
00100         
00101         template <typename T>
00102         struct Deleter
00103         {
00104             static void Delete(T* pObj)
00105             { delete pObj; }
00106         };
00107 
00108         
00109         template <typename T, typename Destroyer>
00110         class ConcreteLifetimeTracker : public LifetimeTracker
00111         {
00112         public:
00113             ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
00114                 : LifetimeTracker(longevity)
00115                 , pTracked_(p)
00116                 , destroyer_(d)
00117             {}
00118             
00119             ~ConcreteLifetimeTracker()
00120             { destroyer_(pTracked_); }
00121             
00122         private:
00123             T* pTracked_;
00124             Destroyer destroyer_;
00125         };
00126 
00127         void AtExitFn(); 
00128     
00129     } 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137     template <typename T, typename Destroyer>
00138     void SetLongevity(T* pDynObject, unsigned int longevity,
00139         Destroyer d = Private::Deleter<T>::Delete)
00140     {
00141         using namespace Private;
00142         
00143         TrackerArray pNewArray = static_cast<TrackerArray>(
00144                 std::realloc(pTrackerArray, elements + 1));
00145         if (!pNewArray) throw std::bad_alloc();
00146         
00147         LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
00148             pDynObject, longevity, d);
00149         
00150         
00151         pTrackerArray = pNewArray;
00152         
00153         
00154         TrackerArray pos = std::upper_bound(
00155             pTrackerArray, 
00156             pTrackerArray + elements, 
00157             p, 
00158             LifetimeTracker::Compare);
00159         std::copy_backward(
00160             pos, 
00161             pTrackerArray + elements,
00162             pTrackerArray + elements + 1);
00163         *pos = p;
00164         ++elements;
00165         
00166         
00167         std::atexit(Private::AtExitFn);
00168     }
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176     template <class T> struct CreateUsingNew
00177     {
00178         static T* Create()
00179         { return new T; }
00180         
00181         static void Destroy(T* p)
00182         { delete p; }
00183     };
00184     
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192     template <class T> struct CreateUsingMalloc
00193     {
00194         static T* Create()
00195         {
00196             void* p = std::malloc(sizeof(T));
00197             if (!p) return 0;
00198             return new(p) T;
00199         }
00200         
00201         static void Destroy(T* p)
00202         {
00203             p->~T();
00204             std::free(p);
00205         }
00206     };
00207     
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217     template <class T> struct CreateStatic
00218     {
00219         union MaxAlign
00220         {
00221             char t_[sizeof(T)];
00222             short int shortInt_;
00223             int int_;
00224             long int longInt_;
00225             float float_;
00226             double double_;
00227             long double longDouble_;
00228             struct Test;
00229             int Test::* pMember_;
00230             int (Test::*pMemberFn_)(int);
00231         };
00232         
00233         static T* Create()
00234         {
00235             static MaxAlign staticMemory_;
00236             return new(&staticMemory_) T;
00237         }
00238         
00239         static void Destroy(T* p)
00240         {
00241             p->~T();
00242         }
00243     };
00244     
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252     template <class T>
00253     struct DefaultLifetime
00254     {
00255         static void ScheduleDestruction(T*, void (*pFun)())
00256         { std::atexit(pFun); }
00257         
00258         static void OnDeadReference()
00259         { throw std::logic_error("Dead Reference Detected"); }
00260     };
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269     template <class T>
00270     class PhoenixSingleton
00271     {
00272     public:
00273         static void ScheduleDestruction(T*, void (*pFun)())
00274         {
00275 #ifndef ATEXIT_FIXED
00276             if (!destroyedOnce_)
00277 #endif
00278                 std::atexit(pFun);
00279         }
00280         
00281         static void OnDeadReference()
00282         {
00283 #ifndef ATEXIT_FIXED
00284             destroyedOnce_ = true;
00285 #endif
00286         }
00287         
00288     private:
00289 #ifndef ATEXIT_FIXED
00290         static bool destroyedOnce_;
00291 #endif
00292     };
00293     
00294 #ifndef ATEXIT_FIXED
00295     template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
00296 #endif
00297         
00298 
00299 
00300 
00301 
00302 
00303     namespace Private
00304     {
00305         template <class T>
00306         struct Adapter
00307         {
00308             void operator()(T*) { return pFun_(); }
00309             void (*pFun_)();
00310         };
00311     }
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321     template <class T>
00322     class SingletonWithLongevity
00323     {
00324     public:
00325         static void ScheduleDestruction(T* pObj, void (*pFun)())
00326         {
00327             Private::Adapter<T> adapter = { pFun };
00328             SetLongevity(pObj, GetLongevity(pObj), adapter);
00329         }
00330         
00331         static void OnDeadReference()
00332         { throw std::logic_error("Dead Reference Detected"); }
00333     };
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341     template <class T>
00342     struct NoDestroy
00343     {
00344         static void ScheduleDestruction(T*, void (*)())
00345         {}
00346         
00347         static void OnDeadReference()
00348         {}
00349     };
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358     template
00359     <
00360         typename T,
00361         template <class> class CreationPolicy = CreateUsingNew,
00362         template <class> class LifetimePolicy = DefaultLifetime,
00363         template <class> class ThreadingModel = SingleThreaded
00364     >
00365     class SingletonHolder
00366     {
00367     public:
00368         static T& Instance();
00369         
00370     private:
00371         
00372         static void MakeInstance();
00373         static void DestroySingleton();
00374         
00375         
00376         SingletonHolder();
00377         
00378         
00379         typedef typename ThreadingModel<T*>::VolatileType PtrInstanceType;
00380         static PtrInstanceType pInstance_;
00381         static bool destroyed_;
00382     };
00383     
00384 
00385 
00386 
00387 
00388     template
00389     <
00390         class T,
00391         template <class> class C,
00392         template <class> class L,
00393         template <class> class M
00394     >
00395     typename SingletonHolder<T, C, L, M>::PtrInstanceType
00396         SingletonHolder<T, C, L, M>::pInstance_;
00397 
00398     template
00399     <
00400         class T,
00401         template <class> class C,
00402         template <class> class L,
00403         template <class> class M
00404     >
00405     bool SingletonHolder<T, C, L, M>::destroyed_;
00406 
00407 
00408 
00409 
00410 
00411     template
00412     <
00413         class T,
00414         template <class> class CreationPolicy,
00415         template <class> class LifetimePolicy,
00416         template <class> class ThreadingModel
00417     >
00418     inline T& SingletonHolder<T, CreationPolicy, 
00419         LifetimePolicy, ThreadingModel>::Instance()
00420     {
00421         if (!pInstance_)
00422         {
00423             MakeInstance();
00424         }
00425         return *pInstance_;
00426     }
00427 
00428 
00429 
00430 
00431 
00432     template
00433     <
00434         class T,
00435         template <class> class CreationPolicy,
00436         template <class> class LifetimePolicy,
00437         template <class> class ThreadingModel
00438     >
00439     void SingletonHolder<T, CreationPolicy, 
00440         LifetimePolicy, ThreadingModel>::MakeInstance()
00441     {
00442         typename ThreadingModel<T>::Lock guard;
00443         (void)guard;
00444         
00445         if (!pInstance_)
00446         {
00447             if (destroyed_)
00448             {
00449                 LifetimePolicy<T>::OnDeadReference();
00450                 destroyed_ = false;
00451             }
00452             pInstance_ = CreationPolicy<T>::Create();
00453             LifetimePolicy<T>::ScheduleDestruction(pInstance_, 
00454                 &DestroySingleton);
00455         }
00456     }
00457 
00458     template
00459     <
00460         class T,
00461         template <class> class CreationPolicy,
00462         template <class> class L,
00463         template <class> class M
00464     >
00465     void SingletonHolder<T, CreationPolicy, L, M>::DestroySingleton()
00466     {
00467         assert(!destroyed_);
00468         CreationPolicy<T>::Destroy(pInstance_);
00469         pInstance_ = 0;
00470         destroyed_ = true;
00471     }
00472 } 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 #endif // SINGLETON_INC_