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
00039 #ifndef BLOCXX_LAZY_GLOBAL_HPP_INCLUDE_GUARD_
00040 #define BLOCXX_LAZY_GLOBAL_HPP_INCLUDE_GUARD_
00041
00042 #include "blocxx/BLOCXX_config.h"
00043 #include "blocxx/ThreadOnce.hpp"
00044 #include "blocxx/GlobalPtr.hpp"
00045
00046 #ifdef BLOCXX_HAVE_STD_TR1_IS_POD
00047 #include "blocxx/StaticAssert.hpp"
00048
00049 #include <tr1/type_traits>
00050 #endif
00051
00052 namespace BLOCXX_NAMESPACE
00053 {
00054
00055 template <typename T, typename PODType>
00056 struct DefaultVariableConstructorFactory
00057 {
00058 static T* create(const PODType& t)
00059 {
00060 return new T(t);
00061 }
00062 };
00063
00113 template <typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType> >
00114 class LazyGlobal
00115 {
00116 #ifdef BLOCXX_HAVE_STD_TR1_IS_POD
00117 BLOCXX_STATIC_ASSERT(std::tr1::is_pod<PODType>::value);
00118 #endif
00119 private:
00120 struct InitPtr
00121 {
00122 InitPtr(T*& p, const PODType& str)
00123 : m_p(p)
00124 , m_pod(str)
00125 { }
00126 T*& m_p;
00127 const PODType& m_pod;
00128
00129 void operator()()
00130 {
00131 m_p = static_cast<T*>(FactoryT::create(m_pod));
00132 }
00133 };
00134
00135 T* getPtr() const
00136 {
00137 callOnce(m_onceFlag, InitPtr(m_p, m_pod));
00138 return m_p;
00139 }
00140
00141 public:
00142 ~LazyGlobal()
00143 {
00144 delete m_p;
00145
00146 m_p = 0;
00147 OnceFlag tmp = BLOCXX_ONCE_INIT;
00148 m_onceFlag = tmp;
00149 }
00150
00151 T& get() const
00152 {
00153 callOnce(m_onceFlag, InitPtr(m_p, m_pod));
00154 return *m_p;
00155 }
00156
00157
00158
00159
00160 operator T&()
00161 {
00162 return get();
00163 }
00164
00165 operator const T&() const
00166 {
00167 return get();
00168 }
00169
00170 template<typename T2>
00171 T& operator=(const T2& rhs)
00172 {
00173
00174 return (get() = rhs);
00175 }
00176
00177
00178
00179 PODType m_pod;
00180 mutable T* m_p;
00181 mutable OnceFlag m_onceFlag;
00182 };
00183
00188 #define BLOCXX_LAZY_GLOBAL_INIT(...) { __VA_ARGS__, 0, BLOCXX_ONCE_INIT }
00189
00190 }
00191
00192
00193 #endif