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 #ifndef UTILS_HPP
00026 #define UTILS_HPP
00027
00028 #ifdef MAPNIK_THREADSAFE
00029 #include <boost/thread/mutex.hpp>
00030 #endif
00031
00032
00033 #include <stdexcept>
00034 #include <cstdlib>
00035 #include <limits>
00036 #include <ctime>
00037 #include <sstream>
00038 #include <iostream>
00039 #include <algorithm>
00040 #include <cmath>
00041
00042 namespace mapnik
00043 {
00044 #ifdef MAPNIK_THREADSAFE
00045 using boost::mutex;
00046 #endif
00047
00048 template <typename T>
00049 class CreateUsingNew
00050 {
00051 public:
00052 static T* create()
00053 {
00054 return new T;
00055 }
00056 static void destroy(T* obj)
00057 {
00058 delete obj;
00059 }
00060 };
00061
00062 template <typename T>
00063 class CreateStatic
00064 {
00065 private:
00066 union MaxAlign
00067 {
00068 char t_[sizeof(T)];
00069 short int shortInt_;
00070 int int_;
00071 long int longInt_;
00072 float float_;
00073 double double_;
00074 long double longDouble_;
00075 struct Test;
00076 int Test::* pMember_;
00077 int (Test::*pMemberFn_)(int);
00078 };
00079
00080 public:
00081
00082 static T* create()
00083 {
00084 static MaxAlign staticMemory;
00085 return new(&staticMemory) T;
00086 }
00087 #ifdef __SUNPRO_CC
00088
00089 static void destroy(T* obj)
00090 #else
00091 static void destroy(volatile T* obj)
00092 #endif
00093 {
00094 obj->~T();
00095 }
00096 };
00097
00098 template <typename T,
00099 template <typename T> class CreatePolicy=CreateStatic> class singleton
00100 {
00101 #ifdef __SUNPRO_CC
00102
00103
00104
00105
00106 friend class CreatePolicy;
00107 #else
00108 friend class CreatePolicy<T>;
00109 #endif
00110 static T* pInstance_;
00111 static bool destroyed_;
00112 singleton(const singleton &rhs);
00113 singleton& operator=(const singleton&);
00114 static void onDeadReference()
00115 {
00116 throw std::runtime_error("dead reference!");
00117 }
00118
00119 static void DestroySingleton()
00120 {
00121 CreatePolicy<T>::destroy(pInstance_);
00122 pInstance_ = 0;
00123 destroyed_=true;
00124 #ifdef MAPNIK_DEBUG
00125 std::clog << " destroyed singleton \n";
00126 #endif
00127 }
00128
00129 protected:
00130 #ifdef MAPNIK_THREADSAFE
00131 static mutex mutex_;
00132 #endif
00133 singleton() {}
00134 public:
00135 static T* instance()
00136 {
00137 if (!pInstance_)
00138 {
00139 #ifdef MAPNIK_THREADSAFE
00140 mutex::scoped_lock lock(mutex_);
00141 #endif
00142 if (!pInstance_)
00143 {
00144
00145 if (destroyed_)
00146 {
00147 onDeadReference();
00148 }
00149 else
00150 {
00151 pInstance_=CreatePolicy<T>::create();
00152
00153 std::atexit(&DestroySingleton);
00154 }
00155 }
00156 }
00157 return pInstance_;
00158 }
00159 };
00160 #ifdef MAPNIK_THREADSAFE
00161 template <typename T,
00162 template <typename T> class CreatePolicy> mutex singleton<T,CreatePolicy>::mutex_;
00163 #endif
00164
00165 template <typename T,
00166 template <typename T> class CreatePolicy> T* singleton<T,CreatePolicy>::pInstance_=0;
00167 template <typename T,
00168 template <typename T> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;
00169
00170 }
00171
00172
00173 #endif //UTILS_HPP