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

Go to the SVN repository for this file.

1 #ifndef CORELIB___GUARD__HPP
2 #define CORELIB___GUARD__HPP
3 
4 /* $Id: guard.hpp 82620 2018-06-16 15:38:08Z lavr $
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  * Authors: Mike DiCuccio
30  *
31  * File Description:
32  * CGuard<> -- implementation of RAII-based locking guard
33  *
34  */
35 
36 #include <corelib/ncbimisc.hpp>
37 
38 
40 
41 
42 ///
43 /// SSimpleLock is a functor to wrap calling Lock(). While this may seem
44 /// excessive, it permits a lot of flexibility in defining what it means
45 /// to acquire a lock
46 ///
47 template <class Resource>
49 {
50  typedef Resource resource_type;
51  void operator()(resource_type& resource) const
52  {
53  resource.Lock();
54  }
55 };
56 
57 
58 ///
59 /// SSimpleLock is a functor to wrap calling Unlock(). While this may seem
60 /// excessive, it permits a lot of flexibility in defining what it means
61 /// to release a lock
62 ///
63 template <class Resource>
65 {
66  typedef Resource resource_type;
67  void operator()(resource_type& resource) const
68  {
69  resource.Unlock();
70  }
71 };
72 
73 
74 ///
75 /// class CGuard<> implements a templatized "resource acquisition is
76 /// initialization" (RAII) locking guard.
77 ///
78 /// This guard is useful for locking resources in an exception-safe manner.
79 /// The classic use of this is to lock a mutex within a C++ scope, as follows:
80 ///
81 /// void SomeFunction()
82 /// {
83 /// CGuard<CMutex> GUARD(some_mutex);
84 /// [...perform some thread-safe operations...]
85 /// }
86 ///
87 /// If an exception is thrown during the performance of any operations while
88 /// the guard is held, the guarantee of C++ stack-unwinding will force
89 /// the guard's destructor to release whatever resources were acquired.
90 ///
91 ///
92 
95 };
96 
97 
98 /// Base class for CGuard<> template.
100 {
101 public:
102  /// Exception reporting options.
104  eReport, ///< Use ERR_POST to report exceptions.
105  eSilent ///< Silently discard exceptions.
106  };
107 
108 protected:
109  static void ReportException(std::exception& ex);
110 };
111 
112 
113 template <class Resource,
114  class Lock = SSimpleLock<Resource>,
115  class Unlock = SSimpleUnlock<Resource>,
117 class CGuard : public CGuard_Base
118 {
119 public:
120  typedef Resource resource_type;
122  typedef Lock lock_type;
123  typedef Unlock unlock_type;
125 
126  explicit CGuard(EEmptyGuard /*empty*/)
127  {
128  }
129 
130  /// This constructor locks the resource passed.
131  explicit CGuard(resource_type& resource)
132  {
133  Guard(resource);
134  }
135 
136  explicit CGuard(EEmptyGuard /*empty*/,
137  const lock_type& lock,
138  const unlock_type& unlock = unlock_type())
139  : m_Data(lock, pair_base_member<unlock_type, resource_ptr>(unlock, 0))
140  {
141  }
142 
143  /// This constructor locks the resource passed.
144  explicit CGuard(resource_type& resource,
145  const lock_type& lock,
146  const unlock_type& unlock = unlock_type())
147  : m_Data(lock, pair_base_member<unlock_type, resource_ptr>(unlock, 0))
148  {
149  Guard(resource);
150  }
151 
152  /// Destructor releases the resource.
154  {
155  try {
156  Release();
157  } catch(std::exception& ex) {
158  // catch and report or ignore std exceptions in destructor
159  if (ReportExceptions == eReport) {
160  ReportException(ex);
161  }
162  }
163  }
164 
165  /// Manually force the resource to be released.
166  void Release()
167  {
168  if ( GetResource() ) {
169  GetUnlock()(*GetResource());
170  GetResource() = 0;
171  }
172  }
173 
174  /// Manually force the guard to protect some other resource.
175  void Guard(resource_type& resource)
176  {
177  Release();
178  GetLock()(resource);
179  GetResource() = &resource;
180  }
181 
182 protected:
184  {
185  return m_Data.second().second();
186  }
188  {
189  return m_Data.first();
190  }
192  {
193  return m_Data.second().first();
194  }
195 
196 private:
197  /// Maintain a pointer to the original resource that is being guarded
201 
202 private:
203  // prevent copying
206 };
207 
208 
209 ///
210 /// CNoLock is a simple no-op lock which does no real locking.
211 /// The class can be used as a template argument instead of normal
212 /// locks (e.g. CMutex).
213 ///
214 class CNoLock
215 {
216 public:
219 
220  void Lock (void) const {}
221  void Unlock(void) const {}
222 };
223 
224 
226 
227 #endif // CORELIB___GUARD__HPP
Base class for CGuard<> template.
Definition: guard.hpp:100
static void ReportException(std::exception &ex)
Definition: guard.cpp:42
EReportExceptions
Exception reporting options.
Definition: guard.hpp:103
@ eReport
Use ERR_POST to report exceptions.
Definition: guard.hpp:104
~CGuard()
Destructor releases the resource.
Definition: guard.hpp:153
CGuard(const CGuard< resource_type, lock_type, unlock_type > &)
void operator=(const CGuard< resource_type, lock_type, unlock_type > &)
void Guard(resource_type &resource)
Manually force the guard to protect some other resource.
Definition: guard.hpp:175
Unlock unlock_type
Definition: guard.hpp:123
CGuard(resource_type &resource, const lock_type &lock, const unlock_type &unlock=unlock_type())
This constructor locks the resource passed.
Definition: guard.hpp:144
Lock lock_type
Definition: guard.hpp:122
pair_base_member< lock_type, pair_base_member< unlock_type, resource_ptr > > m_Data
Maintain a pointer to the original resource that is being guarded.
Definition: guard.hpp:200
CGuard(EEmptyGuard)
Definition: guard.hpp:126
unlock_type & GetUnlock(void)
Definition: guard.hpp:191
CGuard(resource_type &resource)
This constructor locks the resource passed.
Definition: guard.hpp:131
CGuard< Resource, Lock, Unlock, ReportExceptions > TThisType
Definition: guard.hpp:124
resource_ptr & GetResource(void)
Definition: guard.hpp:183
void Release()
Manually force the resource to be released.
Definition: guard.hpp:166
CGuard(EEmptyGuard, const lock_type &lock, const unlock_type &unlock=unlock_type())
Definition: guard.hpp:136
resource_type * resource_ptr
Definition: guard.hpp:121
lock_type & GetLock(void)
Definition: guard.hpp:187
Resource resource_type
Definition: guard.hpp:120
CNoLock is a simple no-op lock which does no real locking.
Definition: guard.hpp:215
void Lock(void) const
Definition: guard.hpp:220
CGuard< CNoLock > TReadLockGuard
Definition: guard.hpp:217
CGuard< CNoLock > TWriteLockGuard
Definition: guard.hpp:218
void Unlock(void) const
Definition: guard.hpp:221
IRegistry –.
Definition: ncbireg.hpp:73
Template used for empty base class optimization.
Definition: ncbimisc.hpp:246
const first_type & first() const
Definition: ncbimisc.hpp:269
const second_type & second() const
Definition: ncbimisc.hpp:278
#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
EEmptyGuard
class CGuard<> implements a templatized "resource acquisition is initialization" (RAII) locking guard...
Definition: guard.hpp:93
@ eEmptyGuard
Definition: guard.hpp:94
Miscellaneous common-use basic types and functionality.
SSimpleLock is a functor to wrap calling Lock().
Definition: guard.hpp:49
void operator()(resource_type &resource) const
Definition: guard.hpp:51
Resource resource_type
Definition: guard.hpp:50
SSimpleReadLock –.
Definition: ncbimtx.hpp:909
SSimpleLock is a functor to wrap calling Unlock().
Definition: guard.hpp:65
Resource resource_type
Definition: guard.hpp:66
void operator()(resource_type &resource) const
Definition: guard.hpp:67
Modified on Tue May 21 10:55:33 2024 by modify_doxy.py rev. 669887