00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015 #ifndef LOKI_SINGLETON_INC_
00016 #define LOKI_SINGLETON_INC_
00017
00018
00019
00020
00021 #include "LokiExport.h"
00022 #include "Threads.h"
00023 #include <algorithm>
00024 #include <stdexcept>
00025 #include <cassert>
00026 #include <cstdlib>
00027 #include <new>
00028 #include <vector>
00029 #include <list>
00030 #include <memory>
00031
00032 #ifdef _MSC_VER
00033 #define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl
00034 #else
00035 #define LOKI_C_CALLING_CONVENTION_QUALIFIER
00036 #endif
00037
00050
00051
00052
00053 namespace Loki
00054 {
00055 typedef void (LOKI_C_CALLING_CONVENTION_QUALIFIER *atexit_pfn_t)();
00056
00057 namespace Private
00058 {
00059
00060 #ifndef LOKI_MAKE_DLL
00061 void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn();
00062 #else
00063 void LOKI_EXPORT AtExitFn();
00064 #endif
00065
00066 class LifetimeTracker;
00067
00068 #define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
00069 #ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
00070
00071
00072
00073 typedef std::list<LifetimeTracker*> TrackerArray;
00074 extern LOKI_EXPORT TrackerArray* pTrackerArray;
00075 #else
00076
00077 typedef LifetimeTracker** TrackerArray;
00078 extern TrackerArray pTrackerArray;
00079 extern unsigned int elements;
00080 #endif
00081
00083
00084
00086
00087 class LifetimeTracker
00088 {
00089 public:
00090 LifetimeTracker(unsigned int x) : longevity_(x)
00091 {}
00092
00093 virtual ~LifetimeTracker() = 0;
00094
00095 static bool Compare(const LifetimeTracker* lhs,
00096 const LifetimeTracker* rhs)
00097 {
00098 return lhs->longevity_ > rhs->longevity_;
00099 }
00100
00101 private:
00102 unsigned int longevity_;
00103 };
00104
00105
00106 inline LifetimeTracker::~LifetimeTracker() {}
00107
00108
00109 template <typename T>
00110 struct Deleter
00111 {
00112 typedef void (*Type)(T*);
00113 static void Delete(T* pObj)
00114 { delete pObj; }
00115 };
00116
00117
00118 template <typename T, typename Destroyer>
00119 class ConcreteLifetimeTracker : public LifetimeTracker
00120 {
00121 public:
00122 ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
00123 : LifetimeTracker(longevity)
00124 , pTracked_(p)
00125 , destroyer_(d)
00126 {}
00127
00128 ~ConcreteLifetimeTracker()
00129 { destroyer_(pTracked_); }
00130
00131 private:
00132 T* pTracked_;
00133 Destroyer destroyer_;
00134 };
00135
00136 }
00137
00144
00145 #ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
00146
00147 template <typename T, typename Destroyer>
00148 void SetLongevity(T* pDynObject, unsigned int longevity,
00149 Destroyer d)
00150 {
00151 using namespace Private;
00152
00153
00154 if(pTrackerArray==0)
00155 pTrackerArray = new TrackerArray;
00156
00157
00158 std::auto_ptr<LifetimeTracker>
00159 p( new ConcreteLifetimeTracker<T, Destroyer>(pDynObject, longevity, d) );
00160
00161
00162 TrackerArray::iterator pos = std::upper_bound(
00163 pTrackerArray->begin(),
00164 pTrackerArray->end(),
00165 p.get(),
00166 LifetimeTracker::Compare);
00167
00168
00169 pTrackerArray->insert(pos, p.get());
00170
00171
00172 p.release();
00173
00174
00175 std::atexit(Private::AtExitFn);
00176 }
00177
00178 #else
00179
00180 template <typename T, typename Destroyer>
00181 void SetLongevity(T* pDynObject, unsigned int longevity,
00182 Destroyer d)
00183 {
00184 using namespace Private;
00185
00186 TrackerArray pNewArray = static_cast<TrackerArray>(
00187 std::realloc(pTrackerArray,
00188 sizeof(*pTrackerArray) * (elements + 1)));
00189 if (!pNewArray) throw std::bad_alloc();
00190
00191
00192 pTrackerArray = pNewArray;
00193
00194 LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
00195 pDynObject, longevity, d);
00196
00197
00198 TrackerArray pos = std::upper_bound(
00199 pTrackerArray,
00200 pTrackerArray + elements,
00201 p,
00202 LifetimeTracker::Compare);
00203 std::copy_backward(
00204 pos,
00205 pTrackerArray + elements,
00206 pTrackerArray + elements + 1);
00207 *pos = p;
00208 ++elements;
00209
00210
00211 std::atexit(Private::AtExitFn);
00212 }
00213
00214 #endif
00215
00216 template <typename T>
00217 void SetLongevity(T* pDynObject, unsigned int longevity,
00218 typename Private::Deleter<T>::Type d = Private::Deleter<T>::Delete)
00219 {
00220 SetLongevity<T, typename Private::Deleter<T>::Type>(pDynObject, longevity, d);
00221 }
00222
00230 template <class T> struct CreateUsingNew
00231 {
00232 static T* Create()
00233 { return new T; }
00234
00235 static void Destroy(T* p)
00236 { delete p; }
00237 };
00238
00247 template<template<class> class Alloc>
00248 struct CreateUsing
00249 {
00250 template <class T>
00251 struct Allocator
00252 {
00253 static Alloc<T> allocator;
00254
00255 static T* Create()
00256 {
00257 return new (allocator.allocate(1)) T;
00258 }
00259
00260 static void Destroy(T* p)
00261 {
00262
00263 p->~T();
00264 allocator.deallocate(p,1);
00265 }
00266 };
00267 };
00268
00277 template <class T> struct CreateUsingMalloc
00278 {
00279 static T* Create()
00280 {
00281 void* p = std::malloc(sizeof(T));
00282 if (!p) return 0;
00283 return new(p) T;
00284 }
00285
00286 static void Destroy(T* p)
00287 {
00288 p->~T();
00289 std::free(p);
00290 }
00291 };
00292
00293
00304 template <class T> struct CreateStatic
00305 {
00306
00307 #ifdef _MSC_VER
00308 #pragma warning( push )
00309 #pragma warning( disable : 4121 )
00310
00311 #endif // _MSC_VER
00312
00313 union MaxAlign
00314 {
00315 char t_[sizeof(T)];
00316 short int shortInt_;
00317 int int_;
00318 long int longInt_;
00319 float float_;
00320 double double_;
00321 long double longDouble_;
00322 struct Test;
00323 int Test::* pMember_;
00324 int (Test::*pMemberFn_)(int);
00325 };
00326
00327 #ifdef _MSC_VER
00328 #pragma warning( pop )
00329 #endif // _MSC_VER
00330
00331 static T* Create()
00332 {
00333 static MaxAlign staticMemory_;
00334 return new(&staticMemory_) T;
00335 }
00336
00337 static void Destroy(T* p)
00338 {
00339 p->~T();
00340 }
00341 };
00342
00351 template <class T>
00352 struct DefaultLifetime
00353 {
00354 static void ScheduleDestruction(T*, atexit_pfn_t pFun)
00355 { std::atexit(pFun); }
00356
00357 static void OnDeadReference()
00358 { throw std::logic_error("Dead Reference Detected"); }
00359 };
00360
00369 template <class T>
00370 class PhoenixSingleton
00371 {
00372 public:
00373 static void ScheduleDestruction(T*, atexit_pfn_t pFun)
00374 {
00375 #ifndef ATEXIT_FIXED
00376 if (!destroyedOnce_)
00377 #endif
00378 std::atexit(pFun);
00379 }
00380
00381 static void OnDeadReference()
00382 {
00383 #ifndef ATEXIT_FIXED
00384 destroyedOnce_ = true;
00385 #endif
00386 }
00387
00388 private:
00389 #ifndef ATEXIT_FIXED
00390 static bool destroyedOnce_;
00391 #endif
00392 };
00393
00394 #ifndef ATEXIT_FIXED
00395 template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
00396 #endif
00397
00399
00416 template <class T>
00417 class DeletableSingleton
00418 {
00419 public:
00420
00421 static void ScheduleDestruction(T*, atexit_pfn_t pFun)
00422 {
00423 static bool firstPass = true;
00424 isDead = false;
00425 deleter = pFun;
00426 if (firstPass || needCallback)
00427 {
00428 std::atexit(atexitCallback);
00429 firstPass = false;
00430 needCallback = false;
00431 }
00432 }
00433
00434 static void OnDeadReference()
00435 {
00436 }
00438 static void GracefulDelete()
00439 {
00440 if (isDead)
00441 return;
00442 isDead = true;
00443 deleter();
00444 }
00445
00446 protected:
00447 static atexit_pfn_t deleter;
00448 static bool isDead;
00449 static bool needCallback;
00450
00451 static void atexitCallback()
00452 {
00453 #ifdef ATEXIT_FIXED
00454 needCallback = true;
00455 #else
00456 needCallback = false;
00457 #endif
00458 GracefulDelete();
00459 }
00460 };
00461
00462 template <class T>
00463 atexit_pfn_t DeletableSingleton<T>::deleter = 0;
00464
00465 template <class T>
00466 bool DeletableSingleton<T>::isDead = true;
00467
00468 template <class T>
00469 bool DeletableSingleton<T>::needCallback = true;
00470
00472
00473
00475
00476 namespace Private
00477 {
00478 template <class T>
00479 struct Adapter
00480 {
00481 void operator()(T*) { return pFun_(); }
00482 atexit_pfn_t pFun_;
00483 };
00484 }
00485
00495 template <class T>
00496 class SingletonWithLongevity
00497 {
00498 public:
00499 static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun)
00500 {
00501 Private::Adapter<T> adapter = { pFun };
00502 SetLongevity(pObj, GetLongevity(pObj), adapter);
00503 }
00504
00505 static void OnDeadReference()
00506 { throw std::logic_error("Dead Reference Detected"); }
00507 };
00508
00516 template <class T>
00517 struct NoDestroy
00518 {
00519 static void ScheduleDestruction(T*, atexit_pfn_t)
00520 {}
00521
00522 static void OnDeadReference()
00523 {}
00524 };
00525
00526
00537 namespace LongevityLifetime
00538 {
00549 template <unsigned int Longevity, class T>
00550 class SingletonFixedLongevity
00551 {
00552 public:
00553 virtual ~SingletonFixedLongevity() {}
00554
00555 static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun)
00556 {
00557 Private::Adapter<T> adapter = { pFun };
00558 SetLongevity(pObj, Longevity , adapter);
00559 }
00560
00561 static void OnDeadReference()
00562 { throw std::logic_error("Dead Reference Detected"); }
00563 };
00564
00568 template <class T>
00569 struct DieLast : SingletonFixedLongevity<0xFFFFFFFF ,T>
00570 {};
00571
00575 template <class T>
00576 struct DieDirectlyBeforeLast : SingletonFixedLongevity<0xFFFFFFFF-1 ,T>
00577 {};
00578
00582 template <class T>
00583 struct DieFirst : SingletonFixedLongevity<0,T>
00584 {};
00585
00586 }
00587
00606 class FollowIntoDeath
00607 {
00608 template<class T>
00609 class Followers
00610 {
00611 typedef std::vector<atexit_pfn_t> Container;
00612 typedef typename Container::iterator iterator;
00613 static Container* followers_;
00614
00615 public:
00616 static void Init()
00617 {
00618 static bool done = false;
00619 if(!done)
00620 {
00621 followers_ = new Container;
00622 done = true;
00623 }
00624 }
00625
00626 static void AddFollower(atexit_pfn_t ae)
00627 {
00628 Init();
00629 followers_->push_back(ae);
00630 }
00631
00632 static void DestroyFollowers()
00633 {
00634 Init();
00635 for(iterator it = followers_->begin();it != followers_->end();++it)
00636 (*it)();
00637 delete followers_;
00638 }
00639 };
00640
00641 public:
00642
00646 template<template <class> class Lifetime>
00647 struct With
00648 {
00651 template<class Master>
00652 struct AsMasterLifetime
00653 {
00654 static void ScheduleDestruction(Master* pObj, atexit_pfn_t pFun)
00655 {
00656 Followers<Master>::Init();
00657 Lifetime<Master>::ScheduleDestruction(pObj, pFun);
00658
00659
00660
00661
00662
00663 Lifetime<Followers<Master> >::ScheduleDestruction(0,Followers<Master>::DestroyFollowers);
00664 }
00665
00666 static void OnDeadReference()
00667 {
00668 throw std::logic_error("Dead Reference Detected");
00669 }
00670 };
00671 };
00672
00676 template<class Master>
00677 struct AfterMaster
00678 {
00681 template<class F>
00682 struct IsDestroyed
00683 {
00684 static void ScheduleDestruction(F*, atexit_pfn_t pFun)
00685 {
00686 Followers<Master>::AddFollower(pFun);
00687 }
00688
00689 static void OnDeadReference()
00690 {
00691 throw std::logic_error("Dead Reference Detected");
00692 }
00693 };
00694 };
00695 };
00696
00697 template<class T>
00698 typename FollowIntoDeath::Followers<T>::Container*
00699 FollowIntoDeath::Followers<T>::followers_ = 0;
00700
00701
00702
00717 template
00718 <
00719 typename T,
00720 template <class> class CreationPolicy = CreateUsingNew,
00721 template <class> class LifetimePolicy = DefaultLifetime,
00722 template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
00723 class MutexPolicy = LOKI_DEFAULT_MUTEX
00724 >
00725 class SingletonHolder
00726 {
00727 public:
00728
00730 typedef T ObjectType;
00731
00733 static T& Instance();
00734
00735 private:
00736
00737 static void MakeInstance();
00738 static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton();
00739
00740
00741 SingletonHolder();
00742
00743
00744 typedef typename ThreadingModel<T*,MutexPolicy>::VolatileType PtrInstanceType;
00745 static PtrInstanceType pInstance_;
00746 static bool destroyed_;
00747 };
00748
00750
00752
00753 template
00754 <
00755 class T,
00756 template <class> class C,
00757 template <class> class L,
00758 template <class, class> class M,
00759 class X
00760 >
00761 typename SingletonHolder<T, C, L, M, X>::PtrInstanceType
00762 SingletonHolder<T, C, L, M, X>::pInstance_;
00763
00764 template
00765 <
00766 class T,
00767 template <class> class C,
00768 template <class> class L,
00769 template <class, class> class M,
00770 class X
00771 >
00772 bool SingletonHolder<T, C, L, M, X>::destroyed_;
00773
00775
00777
00778 template
00779 <
00780 class T,
00781 template <class> class CreationPolicy,
00782 template <class> class LifetimePolicy,
00783 template <class, class> class ThreadingModel,
00784 class MutexPolicy
00785 >
00786 inline T& SingletonHolder<T, CreationPolicy,
00787 LifetimePolicy, ThreadingModel, MutexPolicy>::Instance()
00788 {
00789 if (!pInstance_)
00790 {
00791 MakeInstance();
00792 }
00793 return *pInstance_;
00794 }
00795
00797
00799
00800 template
00801 <
00802 class T,
00803 template <class> class CreationPolicy,
00804 template <class> class LifetimePolicy,
00805 template <class, class> class ThreadingModel,
00806 class MutexPolicy
00807 >
00808 void SingletonHolder<T, CreationPolicy,
00809 LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance()
00810 {
00811 typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard;
00812 (void)guard;
00813
00814 if (!pInstance_)
00815 {
00816 if (destroyed_)
00817 {
00818 destroyed_ = false;
00819 LifetimePolicy<T>::OnDeadReference();
00820 }
00821 pInstance_ = CreationPolicy<T>::Create();
00822 LifetimePolicy<T>::ScheduleDestruction(pInstance_,
00823 &DestroySingleton);
00824 }
00825 }
00826
00827 template
00828 <
00829 class T,
00830 template <class> class CreationPolicy,
00831 template <class> class L,
00832 template <class, class> class M,
00833 class X
00834 >
00835 void LOKI_C_CALLING_CONVENTION_QUALIFIER
00836 SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton()
00837 {
00838 assert(!destroyed_);
00839 CreationPolicy<T>::Destroy(pInstance_);
00840 pInstance_ = 0;
00841 destroyed_ = true;
00842 }
00843
00844
00858
00859 #ifndef LOKI_SINGLETON_EXPORT
00860 #define LOKI_SINGLETON_EXPORT
00861 #endif
00862
00863 template<class T>
00864 class LOKI_SINGLETON_EXPORT Singleton
00865 {
00866 public:
00867 static T& Instance();
00868 };
00869
00870 }
00871
00872
00876
00877 #define LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER) \
00878 namespace Loki \
00879 { \
00880 template<> \
00881 SHOLDER::ObjectType& Singleton<SHOLDER::ObjectType>::Instance() \
00882 { \
00883 return SHOLDER::Instance(); \
00884 } \
00885 }
00886
00887
00888 #endif // end file guardian
00889