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 
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
47 #include "blocxx/StaticAssert.hpp"
48 
49 #include <tr1/type_traits>
50 #endif
51 
52 namespace 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 
129  void operator()()
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