blocxx
|
This class can be used to store a global variable that is lazily initialized in a thread safe manner. More...
#include <LazyGlobal.hpp>
Classes | |
struct | InitPtr |
Public Member Functions | |
~LazyGlobal () | |
T & | get () const |
operator T & () | |
operator const T & () const | |
template<typename T2 > | |
T & | operator= (const T2 &rhs) |
Public Attributes | |
PODType | m_pod |
T * | m_p |
OnceFlag | m_onceFlag |
Private Member Functions | |
T * | getPtr () const |
This class can be used to store a global variable that is lazily initialized in a thread safe manner.
It is intended as a solution to the common C++ issue with the ordering of constructor invocations during the dynamic initialization phase. See http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 for a description and for some possible solutions. Unfortunately the soultions presented in the C++ FAQ are not thread-safe on all platforms (some versions of g++ & C standard library can initialize function-scope static variables in a thread-safe manner) and can't be used by BloCxx.
A LazyGlobal instance consists of a pointer to T that is lazily constructed and deleted when the global variable goes out of scope, an instance of PODType that is used to pass to the constructor of T when it is newed, and a ThreadOnce instance that is used to ensure the pointer is constructed in a thread safe manner.
LazyGlobal is a POD type with a destructor, and thus must be initialized using POD initialization syntax: LazyGlobal<T, PODType> myGlobalVar = BLOCXX_LAZY_GLOBAL_INIT(pod); Doing initialization in this manner happens during the static initialization phase, before any code is run, and so avoids the ordering problem. Take care that the argument is truly static data and not the result of running a function or constructor.
The pointer will be lazily constructed. The first time get() or a conversion operator is called, a new T (or derived) will be instantiated by a call to FactoryT::create(m_pod). The default type for FactoryT allocates a new instance of T passing the variable m_pod of type PODType to the constructor. The initialization is done in a thread safe manner. The double checked locking pattern is used, which doesn't have a large overhead.
No copy or assignment of LazyGlobal variables should ever be done. This cannot be enforced while maintaining the POD initialization of the class.
Conversion operators to T& and const T& are provided so that a LazyGlobal can be used wherever a T would be used.
All calls to get() or the conversion operators are thread safe.
Gotchas to be aware of:
T | The type of the pointer. |
PODType | The type of the POD data that can be passed to the constructor of T. This must be a POD type. If the compiler has a functional std::tr1::is_pod<>, then this will be enforced at compile time. |
FactoryT | To create the T*, FactoryT::create() will be called with 1 parameter, the m_pod variable of type PODType. The return type must be convertible to a T*. The default DefaultVariableConstructorFactory will return a new T passing m_pod as a single argument to the constructor. The factory function should not access instances that may not be initialized, such as a dynamic global or static object, because the factory function may be run at any point during the dynamic initialization phase and there is no guarantee that the instance is already initialized. It is best to only refer to the POD data passed as an argument. |
Definition at line 114 of file LazyGlobal.hpp.
BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::~LazyGlobal | ( | ) | [inline] |
Definition at line 142 of file LazyGlobal.hpp.
T& BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::get | ( | ) | const [inline] |
Definition at line 151 of file LazyGlobal.hpp.
Referenced by BLOCXX_NAMESPACE::Socket::createShutDownMechanism(), BLOCXX_NAMESPACE::Socket::deleteShutDownMechanism(), and BLOCXX_NAMESPACE::Socket::shutdownAllSockets().
T* BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::getPtr | ( | ) | const [inline, private] |
Definition at line 135 of file LazyGlobal.hpp.
BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::operator const T & | ( | ) | const [inline] |
Definition at line 165 of file LazyGlobal.hpp.
BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::operator T & | ( | ) | [inline] |
Definition at line 160 of file LazyGlobal.hpp.
T& BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::operator= | ( | const T2 & | rhs | ) | [inline] |
Definition at line 171 of file LazyGlobal.hpp.
OnceFlag BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::m_onceFlag [mutable] |
Definition at line 181 of file LazyGlobal.hpp.
Referenced by BLOCXX_NAMESPACE::LazyGlobal< Socket::ShutDownMechanism_t, int, ShutDownMechanismFactory >::get(), BLOCXX_NAMESPACE::LazyGlobal< Socket::ShutDownMechanism_t, int, ShutDownMechanismFactory >::getPtr(), and BLOCXX_NAMESPACE::LazyGlobal< Socket::ShutDownMechanism_t, int, ShutDownMechanismFactory >::~LazyGlobal().
T* BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::m_p [mutable] |
Definition at line 180 of file LazyGlobal.hpp.
Referenced by BLOCXX_NAMESPACE::LazyGlobal< Socket::ShutDownMechanism_t, int, ShutDownMechanismFactory >::get(), BLOCXX_NAMESPACE::LazyGlobal< Socket::ShutDownMechanism_t, int, ShutDownMechanismFactory >::getPtr(), and BLOCXX_NAMESPACE::LazyGlobal< Socket::ShutDownMechanism_t, int, ShutDownMechanismFactory >::~LazyGlobal().
PODType BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::m_pod |