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_