NCBI C++ ToolKit
ncbi_autoinit.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef NCBI_AUTOINIT__HPP
2 #define NCBI_AUTOINIT__HPP
3 
4 /* $Id: ncbi_autoinit.hpp 68387 2015-08-03 18:22:34Z grichenk $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author: Aleksey Grichenko
30  *
31  * File Description:
32  * Auto-init variables - create on demand, destroy on termination. This
33  * classes should not be used for static variables.
34  * If you need a static auto-init variable, use
35  * CSafeStaticPtr/Ref instead.
36  *
37  * CAutoInitPtr_Base:: -- base class for CAutoInitPtr<> and CAutoInitRef<>
38  * CAutoInitPtr<>:: -- create variable on demand, destroy on CAutoInitPtr
39  * destruction
40  * CAutoInitRef<>:: -- create CObject-derived variable on demand,
41  * destroy on CAutoInitRef destruction
42  *
43  */
44 
45 #include <corelib/ncbistl.hpp>
46 #include <corelib/ncbiobj.hpp>
47 #include <corelib/ncbimtx.hpp>
48 #include <corelib/ncbi_limits.h>
49 #include <set>
50 
52 
53 
54 /////////////////////////////////////////////////////////////////////////////
55 ///
56 /// CAutoInitPtr_Base::
57 ///
58 /// Base class for CAutoInitPtr<> and CAutoInitRef<> templates.
59 
61 {
62 public:
63  /// User cleanup function type
64  typedef void (*FUserCleanup)(void* ptr);
65 
66  ~CAutoInitPtr_Base(void);
67 
68  bool IsInitialized(void) const;
69 
70 protected:
71  /// Cleanup function type used by derived classes
72  typedef void (*FSelfCleanup)(void** ptr);
73 
74  /// Constructor.
75  ///
76  /// @param self_cleanup
77  /// Cleanup function to be executed on destruction,
78  /// provided by a derived class.
79  /// @param user_cleanup
80  /// User-provided cleanup function to be executed on destruction.
81  CAutoInitPtr_Base(FSelfCleanup self_cleanup,
82  FUserCleanup user_cleanup = 0)
83  : m_Ptr(0),
84  m_SelfCleanup(self_cleanup),
85  m_UserCleanup(user_cleanup)
86  {}
87 
88  // Make sure the pointer is uninitialized, _ASSERT otherwise.
89  void AssertUninitialized(void) const;
90 
91  /// Pointer to the data
92  void* m_Ptr;
93 
95 
96 private:
97  FSelfCleanup m_SelfCleanup; // Derived class' cleanup function
98  FUserCleanup m_UserCleanup; // User-provided cleanup function
99 
100  void x_Cleanup(void)
101  {
102  if ( m_UserCleanup )
103  m_UserCleanup(m_Ptr);
104  if ( m_SelfCleanup )
105  m_SelfCleanup(&m_Ptr);
106  }
107 };
108 
109 
110 /////////////////////////////////////////////////////////////////////////////
111 //
112 /// CAutoInitPtr<>::
113 ///
114 /// For simple on-demand variables.
115 /// Create the variable of type "T" on demand,
116 /// destroy it on the CAutoInitPtr termination.
117 /// The class should not be used for static variables,
118 /// use CSafeStaticPtr class instead.
119 
120 template <class T>
122 {
123 public:
124  /// Constructor.
125  ///
126  /// @param user_cleanup
127  /// User-provided cleanup function to be executed on destruction.
128  /// @sa CAutoInitPtr_Base
129  CAutoInitPtr(FUserCleanup user_cleanup = 0)
130  : CAutoInitPtr_Base(x_SelfCleanup, user_cleanup)
131  {}
132 
133  /// Create the variable if not created yet, return the reference
134  T& Get(void)
135  {
136  if ( !m_Ptr ) {
137  x_Init();
138  }
139  return *static_cast<T*> (m_Ptr);
140  }
141  /// Get the existing object or create a new one using the provided
142  /// FUserCreate object.
143  template <class FUserCreate>
144  T& Get(FUserCreate user_create)
145  {
146  if ( !m_Ptr ) {
147  x_Init(user_create);
148  }
149  return *static_cast<T*> (m_Ptr);
150  }
151 
152  T* operator -> (void) { return &Get(); }
153  T& operator * (void) { return Get(); }
154 
155  /// Initialize with an existing object. The object MUST be
156  /// allocated with "new T" -- it will be destroyed with
157  /// "delete object" in the end. Set() works only for
158  /// not yet initialized CAutoInitPtr variables.
159  void Set(T* object);
160 
161 private:
162  // Initialize the object
163  void x_Init(void);
164 
165  template <class FUserCreate>
166  void x_Init(FUserCreate user_create);
167 
168  // "virtual" cleanup function
169  static void x_SelfCleanup(void** ptr)
170  {
171  T* tmp = static_cast<T*> (*ptr);
172  *ptr = 0;
173  delete tmp;
174  }
175 };
176 
177 
178 
179 /////////////////////////////////////////////////////////////////////////////
180 ///
181 /// CAutoInitRef<>::
182 ///
183 /// For on-demand CObject-derived object.
184 /// Create the variable of type "T" using CRef<>
185 /// (to avoid premature destruction).
186 /// The class should not be used for static variables,
187 /// use CSafeStaticRef class instead.
188 
189 template <class T>
191 {
192 public:
193  /// Constructor.
194  ///
195  /// @param user_cleanup
196  /// User-provided cleanup function to be executed on destruction.
197  /// @sa CAutoInitPtr_Base
198  CAutoInitRef(FUserCleanup user_cleanup = 0)
199  : CAutoInitPtr_Base(x_SelfCleanup, user_cleanup)
200  {}
201 
202  /// Create the variable if not created yet, return the reference
203  T& Get(void)
204  {
205  if ( !m_Ptr ) {
206  x_Init();
207  }
208  return *static_cast<T*>(m_Ptr);
209  }
210  /// Get the existing object or create a new one using the provided
211  /// FUserCreate object.
212  template <class FUserCreate>
213  T& Get(FUserCreate user_create)
214  {
215  if ( !m_Ptr ) {
216  x_Init(user_create);
217  }
218  return *static_cast<T*>(m_Ptr);
219  }
220 
221  T* operator -> (void) { return &Get(); }
222  T& operator * (void) { return Get(); }
223 
224  /// Initialize with an existing object. The object MUST be
225  /// allocated with "new T" to avoid premature destruction.
226  /// Set() works only for un-initialized CAutoInitRef variables.
227  void Set(T* object);
228 
229 private:
230  // Initialize the object and the reference
231  void x_Init(void);
232 
233  template <class FUserCreate>
234  void x_Init(FUserCreate user_create);
235 
236  // "virtual" cleanup function
237  static void x_SelfCleanup(void** ptr)
238  {
239  T* tmp = static_cast<T*>(*ptr);
240  if ( tmp ) {
241  tmp->RemoveReference();
242  *ptr = 0;
243  }
244  }
245 };
246 
247 
248 /////////////////////////////////////////////////////////////////////////////
249 //
250 // Large inline methods
251 
252 inline
254 {
255  CMutexGuard guard(sm_Mutex);
256  return m_Ptr != NULL;
257 }
258 
259 
260 template <class T>
261 inline
262 void CAutoInitPtr<T>::Set(T* object)
263 {
264  CMutexGuard guard(sm_Mutex);
265  AssertUninitialized();
266  if ( m_Ptr ) return;
267  m_Ptr = object;
268 }
269 
270 
271 template <class T>
272 inline
274 {
275  CMutexGuard guard(sm_Mutex);
276  if ( m_Ptr ) return;
277  m_Ptr = new T;
278 }
279 
280 
281 template <class T>
282 template <class FUserCreate>
283 inline
284 void CAutoInitPtr<T>::x_Init(FUserCreate user_create)
285 {
286  CMutexGuard guard(sm_Mutex);
287  if ( m_Ptr ) return;
288  m_Ptr = user_create();
289 }
290 
291 
292 template <class T>
293 inline
294 void CAutoInitRef<T>::Set(T* object)
295 {
296  CMutexGuard guard(sm_Mutex);
297  AssertUninitialized();
298  if ( m_Ptr ) return;
299  if ( object ) {
300  object->AddReference();
301  m_Ptr = object;
302  }
303 }
304 
305 
306 template <class T>
307 inline
309 {
310  CMutexGuard guard(sm_Mutex);
311  if ( m_Ptr ) return;
312  CRef<T> ref(new T);
313  ref->AddReference();
314  m_Ptr = ref.Release();
315 }
316 
317 
318 template <class T>
319 template <class FUserCreate>
320 inline
321 void CAutoInitRef<T>::x_Init(FUserCreate user_create)
322 {
323  CMutexGuard guard(sm_Mutex);
324  if ( m_Ptr ) return;
325  CRef<T> ref(user_create());
326  if ( ref ) {
327  ref->AddReference();
328  m_Ptr = ref.Release();
329  }
330 }
331 
332 
334 
335 #endif /* NCBI_AUTOINIT__HPP */
CAutoInitPtr_Base::
void(* FUserCleanup)(void *ptr)
User cleanup function type.
FUserCleanup m_UserCleanup
CAutoInitPtr_Base(FSelfCleanup self_cleanup, FUserCleanup user_cleanup=0)
Constructor.
DECLARE_CLASS_STATIC_MUTEX(sm_Mutex)
void * m_Ptr
Pointer to the data.
bool IsInitialized(void) const
FSelfCleanup m_SelfCleanup
CAutoInitPtr<>::
T * operator->(void)
T & Get(FUserCreate user_create)
Get the existing object or create a new one using the provided FUserCreate object.
static void x_SelfCleanup(void **ptr)
CAutoInitPtr(FUserCleanup user_cleanup=0)
Constructor.
void Set(T *object)
Initialize with an existing object.
T & operator*(void)
void x_Init(void)
T & Get(void)
Create the variable if not created yet, return the reference.
CAutoInitRef<>::
void Set(T *object)
Initialize with an existing object.
T * operator->(void)
T & Get(FUserCreate user_create)
Get the existing object or create a new one using the provided FUserCreate object.
CAutoInitRef(FUserCleanup user_cleanup=0)
Constructor.
T & Get(void)
Create the variable if not created yet, return the reference.
void x_Init(void)
static void x_SelfCleanup(void **ptr)
T & operator*(void)
#define T(s)
Definition: common.h:230
static char tmp[3200]
Definition: utf8.c:42
#define NULL
Definition: ncbistd.hpp:225
TObjectType * Release(void)
Release a reference to the object and return a pointer to the object.
Definition: ncbiobj.hpp:846
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define NCBI_XNCBI_EXPORT
Definition: ncbi_export.h:1283
Multi-threading – mutexes; rw-locks; semaphore.
Portable reference counted smart and weak pointers using CWeakRef, CRef, CObject and CObjectEx.
The NCBI C++/STL use hints.
Modified on Tue Apr 23 07:37:36 2024 by modify_doxy.py rev. 669887