blocxx
LazyGlobal.hpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Quest Software, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Quest Software, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
38
39#ifndef BLOCXX_LAZY_GLOBAL_HPP_INCLUDE_GUARD_
40#define BLOCXX_LAZY_GLOBAL_HPP_INCLUDE_GUARD_
41
42#include "blocxx/BLOCXX_config.h"
43#include "blocxx/ThreadOnce.hpp"
44#include "blocxx/GlobalPtr.hpp"
45
46#ifdef BLOCXX_HAVE_STD_TR1_IS_POD
48
49#include <tr1/type_traits>
50#endif
51
52namespace BLOCXX_NAMESPACE
53{
54
55 template <typename T, typename PODType>
57 {
58 static T* create(const PODType& t)
59 {
60 return new T(t);
61 }
62 };
63
113 template <typename T, typename PODType, typename FactoryT = DefaultVariableConstructorFactory<T, PODType> >
115 {
116#ifdef BLOCXX_HAVE_STD_TR1_IS_POD
117 BLOCXX_STATIC_ASSERT(std::tr1::is_pod<PODType>::value);
118#endif
119 private:
120 struct InitPtr
121 {
122 InitPtr(T*& p, const PODType& str)
123 : m_p(p)
124 , m_pod(str)
125 { }
126 T*& m_p;
127 const PODType& m_pod;
128
130 {
131 m_p = static_cast<T*>(FactoryT::create(m_pod));
132 }
133 };
134
135 T* getPtr() const
136 {
137 callOnce(m_onceFlag, InitPtr(m_p, m_pod));
138 return m_p;
139 }
140
141 public:
143 {
144 delete m_p;
145 // reset these variables in case get() is called after the destructor runs.
146 m_p = 0;
147 OnceFlag tmp = BLOCXX_ONCE_INIT;
148 m_onceFlag = tmp;
149 }
150
151 T& get() const
152 {
153 callOnce(m_onceFlag, InitPtr(m_p, m_pod));
154 return *m_p;
155 }
156
157 // The two different operators are defined because there may be some
158 // global variables marked as const. We'll want them treated
159 // differently.
160 operator T&()
161 {
162 return get();
163 }
164
165 operator const T&() const
166 {
167 return get();
168 }
169
170 template<typename T2>
171 T& operator=(const T2& rhs)
172 {
173 // checking for self assignment is handled by type T
174 return (get() = rhs);
175 }
176
177 // These members should be treated as private. They aren't marked private
178 // because if they are, POD initializer syntax can't be used.
179 PODType m_pod;
180 mutable T* m_p;
181 mutable OnceFlag m_onceFlag;
182 };
183
188#define BLOCXX_LAZY_GLOBAL_INIT(...) { __VA_ARGS__, 0, BLOCXX_ONCE_INIT }
189
190} // end namespace BLOCXX_NAMESPACE
191
192
193#endif
#define BLOCXX_STATIC_ASSERT(B)
This class can be used to store a global variable that is lazily initialized in a thread safe manner.
T & operator=(const T2 &rhs)
Taken from RFC 1321.
void BLOCXX_COMMON_API callOnce(OnceFlag &flag, FuncT F)
The first time callOnce is called with a given onceFlag argument, it calls func with no argument and ...
InitPtr(T *&p, const PODType &str)