HyperspaceExplorer 0.7.1
|
00001 00002 // The Loki Library 00003 // Copyright (c) 2001 by Andrei Alexandrescu 00004 // This code accompanies the book: 00005 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 00006 // Patterns Applied". Copyright (c) 2001. Addison-Wesley. 00007 // Permission to use, copy, modify, distribute and sell this software for any 00008 // purpose is hereby granted without fee, provided that the above copyright 00009 // notice appear in all copies and that both that copyright notice and this 00010 // permission notice appear in supporting documentation. 00011 // The author or Addison-Wesley Longman make no representations about the 00012 // suitability of this software for any purpose. It is provided "as is" 00013 // without express or implied warranty. 00015 #ifndef LOKI_SINGLETON_INC_ 00016 #define LOKI_SINGLETON_INC_ 00017 00018 // $Id$ 00019 00020 #include <algorithm> 00021 #include <stdexcept> 00022 #include <cassert> 00023 #include <cstdlib> 00024 #include <new> 00025 #include <vector> 00026 #include <list> 00027 #include <memory> 00028 00041 00042 00044 00060 namespace Loki 00061 { 00062 00068 00069 template <class T> struct CreateUsingNew 00070 { 00072 static T* Create() 00073 { return new T; } 00074 00076 static void Destroy(T* p) 00077 { delete p; } 00078 }; 00079 00086 00087 template<template<class> class Alloc> 00088 struct CreateUsing 00089 { 00090 template <class T> 00091 struct Allocator 00092 { 00093 static Alloc<T> allocator; 00094 00096 static T* Create() 00097 { 00098 return new (allocator.allocate(1)) T; 00099 } 00100 00102 static void Destroy(T* p) 00103 { 00104 //allocator.destroy(p); 00105 p->~T(); 00106 allocator.deallocate(p,1); 00107 } 00108 }; 00109 }; 00110 00117 00118 template <class T> struct CreateUsingMalloc 00119 { 00121 static T* Create() 00122 { 00123 void* p = std::malloc(sizeof(T)); 00124 if (!p) return 0; 00125 return new(p) T; 00126 } 00127 00129 static void Destroy(T* p) 00130 { 00131 p->~T(); 00132 std::free(p); 00133 } 00134 }; 00135 00136 00145 00146 template <class T> struct CreateStatic 00147 { 00149 union MaxAlign 00150 { 00151 char t_[sizeof(T)]; 00152 short int shortInt_; 00153 int int_; 00154 long int longInt_; 00155 float float_; 00156 double double_; 00157 long double longDouble_; 00158 struct Test; 00159 int Test::* pMember_; 00160 int (Test::*pMemberFn_)(int); 00161 }; 00162 00164 static T* Create() 00165 { 00166 static MaxAlign staticMemory_; 00167 return new(&staticMemory_) T; 00168 } 00169 00171 static void Destroy(T* p) 00172 { 00173 p->~T(); 00174 } 00175 }; 00176 00177 00190 00191 template 00192 < 00193 typename T, 00194 template <class> class CreationPolicy = CreateUsingNew 00195 > 00196 class SingletonHolder 00197 { 00198 public: 00199 00201 typedef T ObjectType; 00202 00204 static T& Instance(); 00205 00206 private: 00207 // Helpers 00208 static void MakeInstance(); 00209 static void DestroySingleton(); 00210 00211 // Protection 00212 SingletonHolder(); 00213 00214 // Data 00215 typedef T* PtrInstanceType; 00216 static PtrInstanceType pInstance_; 00217 static bool destroyed_; 00218 }; 00219 00221 // SingletonHolder's data 00223 00224 template 00225 < 00226 class T, 00227 template <class> class C 00228 > 00229 typename SingletonHolder<T, C>::PtrInstanceType 00230 SingletonHolder<T, C>::pInstance_ = 0; 00231 00232 template 00233 < 00234 class T, 00235 template <class> class C 00236 > 00237 bool SingletonHolder<T, C>::destroyed_ = false; 00238 00240 // SingletonHolder::Instance 00242 00243 template 00244 < 00245 class T, 00246 template <class> class CreationPolicy 00247 > 00248 inline T& SingletonHolder<T, CreationPolicy>::Instance() 00249 { 00250 if (!pInstance_) 00251 { 00252 MakeInstance(); 00253 } 00254 return *pInstance_; 00255 } 00256 00258 // SingletonHolder::MakeInstance (helper for Instance) 00260 00261 template 00262 < 00263 class T, 00264 template <class> class CreationPolicy 00265 > 00266 void SingletonHolder<T, CreationPolicy>::MakeInstance() 00267 { 00268 if (!pInstance_) 00269 { 00270 if (destroyed_) 00271 { 00272 destroyed_ = false; 00273 } 00274 pInstance_ = CreationPolicy<T>::Create(); 00275 } 00276 } 00277 00278 template 00279 < 00280 class T, 00281 template <class> class CreationPolicy 00282 > 00283 void 00284 SingletonHolder<T, CreationPolicy>::DestroySingleton() 00285 { 00286 assert(!destroyed_); 00287 CreationPolicy<T>::Destroy(pInstance_); 00288 pInstance_ = 0; 00289 destroyed_ = true; 00290 } 00291 00292 00304 00305 #ifndef LOKI_SINGLETON_EXPORT 00306 #define LOKI_SINGLETON_EXPORT 00307 #endif 00308 00309 template<class T> 00310 class LOKI_SINGLETON_EXPORT Singleton 00311 { 00312 public: 00313 static T& Instance(); 00314 }; 00315 00316 } // namespace Loki 00317 00318 00322 00323 #define LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER) \ 00324 namespace Loki \ 00325 { \ 00326 template<> \ 00327 SHOLDER::ObjectType& Singleton<SHOLDER::ObjectType>::Instance() \ 00328 { \ 00329 return SHOLDER::Instance(); \ 00330 } \ 00331 } 00332 00333 00334 #endif // end file guardian