Singletons.h

Go to the documentation of this file.
00001 #ifndef __LDK_SINGLETONS_HH__
00002 #define __LDK_SINGLETONS_HH__
00003 
00005 //   Copyright (C) 2003-2006 Lorien Dunn.
00006 //
00007 //   Contact: loriendunn AT users DOT sourceforge DOT net
00008 //
00009 //   This software is provided 'as-is', without any express or implied warranty.
00010 //   In no event will the authors be held liable for any damages arising from
00011 //   the use of this software.
00012 //
00013 //   Permission is granted to anyone to use this software for any purpose,
00014 //   including commercial applications, and to alter it and redistribute it
00015 //   freely, subject to the following restrictions:
00016 //
00017 //   1. The origin of this software must not be misrepresented; you must not
00018 //   claim that you wrote the original software. If you use this software in a
00019 //   product, an acknowledgment in the product documentation would be
00020 //   appreciated but is not required.
00021 //
00022 //   2. Altered source versions must be plainly marked as such, and must not be
00023 //   misrepresented as being the original software.
00024 //
00025 //   3. This notice may not be removed or altered from any source distribution.
00026 //
00028 
00033 
00034 #include "LDK/ThreadLocalStorage.h"
00035 #include "LDK/STLMallocAllocator.h"
00036 #include <vector>
00037 #include <assert.h>
00038 
00039 namespace LDK
00040 {
00041 
00042 typedef void (*SingletonDtor) ();
00043 
00044 #ifdef _MSC_VER
00045 #pragma warning (disable : 4251)
00046 #endif
00047 
00049 
00050 class LDK_API SingletonCleanup
00051 {
00052 private:
00053 
00054     typedef std::vector<SingletonDtor,MallocAllocator<SingletonDtor> > CleanupVec;
00055 
00056     static  CleanupVec mToClean;
00057     static bool mInitialised;
00058 
00059     static void callDtors();
00060 
00061 public:
00062 
00063     static void initialise();
00064     static void addInstance(SingletonDtor dtor);
00065 };
00066 
00067 class LDK_API ThreadLocalCleanup
00068 {
00069 private:
00070 
00071     struct Pair //can't use std::pair because of const issues
00072     {
00073         ThreadLocalDtor mDtor;
00074         void* mInstance;
00075         Pair(ThreadLocalDtor dtor=NULL, void* instance=NULL) :
00076             mDtor(dtor),
00077             mInstance(instance)
00078         {}
00079     };
00080 
00081     typedef std::vector<Pair,MallocAllocator<Pair> > CleanupVec;
00082 
00083     CleanupVec mToClean;
00084     static TLSKey mKey;
00085     static bool mInitialised;
00086 
00087     static void callThreadDtors(void* s);
00088     static void callDtors();
00089 
00090 public:
00091 
00092     static void initialise();
00093     static void addInstance(ThreadLocalDtor dtor, void* instance);
00094 };
00095 
00104 template <class T>
00105 class SingletonStorage
00106 {
00107 public:
00108     typedef T  Type;
00109     typedef T* PointerType;
00110     typedef T& ReferenceType;
00111 protected:
00112     static bool mInitialised;
00113     static PointerType mInstance;
00114     static void destroy()
00115     {
00116         if(mInstance)
00117             delete mInstance;
00118     }
00119 public:
00120     static void initialise()
00121     {
00122         if(!mInitialised)
00123         {
00124             SingletonCleanup::initialise();
00125             try
00126             {
00127                 mInstance = new T();
00128                 mInitialised = true;
00129             }
00130             catch(std::bad_alloc&)
00131             {
00132                 throw LDK_BADALLOC_ERROR;
00133             }
00134             SingletonCleanup::addInstance(SingletonStorage::destroy);
00135         }
00136     }
00137     static ReferenceType instance()
00138     {
00139         assert(mInitialised);
00140         assert(mInstance);
00141         return *mInstance;
00142     }
00143 };
00144 template <class T>
00145 bool SingletonStorage<T>::mInitialised = false;
00146 template <class T>
00147 T* SingletonStorage<T>::mInstance = NULL;
00148 
00149 
00150 
00159 template <class T>
00160 class TLSSingletonStorage
00161 {
00162 public:
00163     typedef T  Type;
00164     typedef T* PointerType;
00165     typedef T& ReferenceType;
00166 protected:
00167     static bool mInitialised;
00168     static TLSKey mKey;
00169     static void destroy(void* obj)
00170     {
00171         if(obj)
00172             delete reinterpret_cast<T*>(obj);
00173     }
00174 public:
00175     static void initialise()
00176     {
00177         if(!mInitialised)
00178         {
00179             ThreadLocalCleanup::initialise();
00180             mKey = threadLocalCreateKey();
00181             mInitialised = true;
00182         }
00183     }
00184     static ReferenceType instance()
00185     {
00186         assert(mInitialised);
00187         PointerType instance = reinterpret_cast<PointerType>(threadLocalGet(mKey));
00188         if(instance)
00189             return *instance;
00190         try
00191         {
00192             instance = new T();
00193         }
00194         catch(std::bad_alloc&)
00195         {
00196             throw LDK_BADALLOC_ERROR;
00197         }
00198         threadLocalSet(mKey, instance);
00199         ThreadLocalCleanup::addInstance(TLSSingletonStorage::destroy,instance);
00200         return *instance;
00201     }
00202 };
00203 
00204 template <class T>
00205 bool TLSSingletonStorage<T>::mInitialised = false;
00206 template <class T>
00207 TLSKey TLSSingletonStorage<T>::mKey = 0;
00208 
00209 #define DEFAULT_SINGLETON_STORAGE TLSSingletonStorage
00210 
00211 
00226 template
00227 <
00228     class T,
00229     template <class> class StoragePolicy=DEFAULT_SINGLETON_STORAGE
00230 >
00231 class Singleton : public StoragePolicy<T>
00232 {
00233 public:
00234     typedef StoragePolicy<T> SP;
00235     typedef typename SP::Type Type;
00236     typedef typename SP::PointerType PointerType;
00237     typedef typename SP::ReferenceType ReferenceType;
00238 protected:
00239     inline Singleton () {}
00240     inline Singleton (const Singleton &) {}
00241     inline ~Singleton() {}
00242     inline void operator=(const Singleton&) {}
00243 public:
00244     inline static void initialise()
00245     {
00246         SP::initialise();
00247     }
00248     inline static ReferenceType instance()
00249     {
00250         return SP::instance();
00251     }
00252 };
00253 
00254 } //namespace LDK
00255 
00256 #ifdef _MSC_VER
00257 #pragma warning (default : 4251)
00258 #endif
00259 
00260 #endif //__LDK_SINGLETONS_HH__

Generated on Fri Aug 17 18:32:26 2007 for LDK by  doxygen 1.5.1