blocxx
Classes | Public Member Functions | Public Attributes | Private Member Functions

BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT > Class Template Reference

This class can be used to store a global variable that is lazily initialized in a thread safe manner. More...

#include <LazyGlobal.hpp>

List of all members.

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

Detailed Description

template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
class BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >

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:

Parameters:
TThe type of the pointer.
PODTypeThe 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.
FactoryTTo 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.


Constructor & Destructor Documentation

template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::~LazyGlobal ( ) [inline]

Definition at line 142 of file LazyGlobal.hpp.


Member Function Documentation

template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
T& BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::get ( ) const [inline]
template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
T* BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::getPtr ( ) const [inline, private]

Definition at line 135 of file LazyGlobal.hpp.

template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::operator const T & ( ) const [inline]

Definition at line 165 of file LazyGlobal.hpp.

template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::operator T & ( ) [inline]

Definition at line 160 of file LazyGlobal.hpp.

template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
template<typename T2 >
T& BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::operator= ( const T2 &  rhs) [inline]

Definition at line 171 of file LazyGlobal.hpp.


Member Data Documentation

template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
OnceFlag BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::m_onceFlag [mutable]
template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
T* BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::m_p [mutable]
template<typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType>>
PODType BLOCXX_NAMESPACE::LazyGlobal< T, PODType, FactoryT >::m_pod

The documentation for this class was generated from the following file: