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

Go to the SVN repository for this file.

1 #ifndef CORELIB___INTERPROCESS_LOCK__HPP
2 #define CORELIB___INTERPROCESS_LOCK__HPP
3 
4 /* $Id: interprocess_lock.hpp 84598 2018-11-20 20:23:54Z ucko $
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: Vladimir Ivanov, Denis Vakatov
30  *
31  *
32  */
33 
34 /// @file interprocess_lock.hpp
35 /// Simple inter-process lock.
36 ///
37 /// Defines classes:
38 /// CInterProcessLock
39 /// PInterProcessLock
40 /// CInterProcessLockException
41 
42 
43 #include <corelib/ncbitime.hpp>
44 #include <corelib/guard.hpp>
45 
46 #if !defined(NCBI_OS_MSWIN) && !defined(NCBI_OS_UNIX)
47 # error "CInterProcessLock is not implemented on this platform"
48 #endif
49 
50 
51 /** @addtogroup Process
52  *
53  * @{
54  */
55 
57 
58 
59 /////////////////////////////////////////////////////////////////////////////
60 ///
61 /// CInterProcessLock --
62 ///
63 /// Simple inter-process lock.
64 ///
65 /// When the process terminates (normally or otherwise) all locks will be
66 /// removed automaticaly. On Unix, the lock file can be left in the
67 /// filesystem, but the lock itself will be removed anyway and the lock file
68 /// can be reused.
69 ///
70 /// Please consider to use class CGuard<> for locking resources in
71 /// an exception-safe manner. See also CInterProcessLock_Guard to help specify
72 /// timeouts for the locking operation when using CGuard<>.
73 ///
74 /// The lock can be safely acquired from different threads (and, with all
75 /// timeouts observed).
76 
78 {
79 public:
80  /// @param name
81  /// Name of the lock.
82  /// The name must be a Unix-path like, and its length must not
83  /// exceed the maximum path length that is specific for the OS where the
84  /// application runs.
85  /// @note
86  /// This constructor will not try to acquire a lock on creation.
87  /// @note
88  /// - On Unix, if a pathless file name is given, then the corresponding
89  /// file will be created in a well-known system-specific location
90  /// (usually as '/var/tmp/<name>'); if the name represents an absolute
91  /// file path, then the exact path will be used to create the lock file.
92  /// - On Windows, no actual files will be created at the specified path.
93  /// @attention
94  /// - Relative paths are not allowed (regardless of the OS).
95  /// - Empty name is not allowed.
96  /// - Locking may not work for the files located on network filesystems
97  /// (like NFS).
98  /// @sa Lock, TryLock, GetName
99  CInterProcessLock(const string& name);
100 
101  /// Call Unlock()
102  ~CInterProcessLock(void);
103 
104  /// @name
105  /// Lock/guard interface (to use with CGuard<> or CInterProcessLock_Guard)
106  /// @{
107  /// Try to acquire the lock.
108  /// On any error, or if the lock is already held by another process and
109  /// it could not be acquired within the allotted time period,
110  /// throw CInterProcessLockException.
111  /// @param timeout
112  /// How much time Lock() should wait before giving up (with error).
113  /// Default timeout value is interpreted as infinite.
114  /// @param granularity
115  /// On the systems (such as Unix) where there is no support for waiting
116  /// for the lock with a timeout, the waiting is implemented using a
117  /// loop of "try to lock" calls. This parameter specifies how much time to
118  /// wait between these calls. It will be auto-limited to the closest
119  /// whole delimiter of the 'timeout' value (and it will never exceed it).
120  /// Default or infinite granularity timeout is converted into:
121  /// MIN(timeout/5, 0.5sec).
122  /// @note
123  /// If 'timeout' is passed infinite, then the 'granularity' parameter
124  /// actually will not be used at all -- both on Windows and on Unix -- as
125  /// they both support a "honest" infinite waiting.
126  /// @note
127  /// One process can acquire the lock more than once -- but it need
128  /// to use the same CInterProcessLock object for Lock(), and then it will
129  /// need to call Unlock() as many times in order to release the lock for
130  /// other processes.
131  /// @note
132  /// If the lock object (such as file on UNIX or system mutex on Windows)
133  /// doesn't exist it will be created.
134  /// @sa TryLock, SetLockTimeout
135  void Lock(const CTimeout& timeout = CTimeout(CTimeout::eInfinite),
136  const CTimeout& granularity = CTimeout(CTimeout::eInfinite));
137 
138  /// Release the lock.
139  /// On any error (including when the lock is not held by the process),
140  /// throw CInterProcessLockException.
141  /// @sa Lock, TryLock, Remove
142  void Unlock(void);
143  /// @}
144 
145  /// Try to acquire the lock.
146  ///
147  /// Acquire the lock if it can be done right away. Return immediately.
148  /// @return
149  /// - TRUE, if the lock has been successfully acquired.
150  /// - FALSE, if the lock is already held by another process
151  /// or if any error occurs.
152  /// @sa Lock
153  bool TryLock(void);
154 
155  /// Call Unlock() and removes lock object from the system.
156  ///
157  /// On Unix, the Unlock() method do not remove used lock file from
158  /// the system, it just release a lock. If you don't need this file
159  /// anymore, use this method to remove it. We cannot remove it
160  /// automaticaly in the Unlock(), because on Unix locking/unlocking
161  /// is not an atomic operations and race condition is possible if
162  /// at time of deleting some other process wait to acquire a lock
163  /// using the same lock file.
164  /// @note
165  /// On Windows, it works almost as Unlock().
166  /// @sa Unlock
167  void Remove(void);
168 
169  /// Get the original name of the lock -- exactly as it was specified
170  /// in the constructor
171  const string& GetName(void) const { return m_Name; }
172 
173  /// Get the internal name of the lock -- as it is being used in the calls
174  /// to the OS (such as '/var/tmp/<name>' rather than just '<name>' on UNIX)
175  const string& GetSystemName(void) const { return m_SystemName; }
176 
177 private:
178  /// Original name of the lock
179  string m_Name;
180  /// Adjusted name of the lock
181  string m_SystemName;
182 
183  /// OS-specific lock handle
184 #if defined(NCBI_OS_UNIX)
185  typedef int TLockHandle;
186 #elif defined(NCBI_OS_MSWIN)
187  typedef HANDLE TLockHandle;
188 #endif
190 };
191 
192 
193 
194 /////////////////////////////////////////////////////////////////////////////
195 ///
196 /// PInterProcessLock --
197 ///
198 /// Helper functor for CGuard<> to e.g. help specify the waiting timeout.
199 ///
200 /// @example
201 /// CInterProcessLock ipl("MyLock");
202 /// CInterProcessLock_Guard ipl_guard
203 /// (ipl,
204 /// PInterProcessLock(3.456, 0.333));
205 
207 {
208 public:
210 
211  PInterProcessLock(const CTimeout& timeout,
212  const CTimeout& granularity = CTimeout(CTimeout::eInfinite))
213  : m_Timeout(timeout),
214  m_Granularity(granularity)
215  {
216  }
217 
218  void operator()(resource_type& resource) const
219  {
220  resource.Lock(m_Timeout, m_Granularity);
221  }
222 
223 private:
226 };
227 
228 
229 /// Convenience typedef for PInterProcessLock
230 /// @sa PInterProcessLock
232 
233 
234 
235 /////////////////////////////////////////////////////////////////////////////
236 ///
237 /// CInterProcessLockException --
238 ///
239 
241 {
242 public:
243  /// Error types that file operations can generate.
244  enum EErrCode {
245  eLockTimeout, ///< The lock could not be acquired in the time allotted
246  eNameError, ///< Incorrect name for a lock
247  eCreateError, ///< Cannot create the lock object in the OS
248  eLockError, ///< Cannot acquire a lock (not eLockTimeout, eCreateError)
249  eUnlockError, ///< Cannot release the lock
250  eMultipleLocks, ///< Attempt to lock already locked object in the same process
251  eNotLocked ///< Attempt to unlock a not-yet-acquired lock
252  };
253 
254  /// Translate from an error code value to its string representation.
255  virtual const char* GetErrCodeString(void) const override;
256 
257  // Standard exception boilerplate code.
259 };
260 
261 
263 
264 
265 /* @} */
266 
267 #endif /* CORELIB___INTERPROCESS_LOCK__HPP */
CCoreException –.
Definition: ncbiexpt.hpp:1476
CInterProcessLockException –.
CInterProcessLock –.
CTimeout – Timeout interval.
Definition: ncbitime.hpp:1693
PInterProcessLock(const CTimeout &timeout, const CTimeout &granularity=CTimeout(CTimeout::eInfinite))
const string & GetSystemName(void) const
Get the internal name of the lock – as it is being used in the calls to the OS (such as '/var/tmp/<na...
CGuard< CInterProcessLock, PInterProcessLock > CInterProcessLock_Guard
Convenience typedef for PInterProcessLock.
EErrCode
Error types that file operations can generate.
string m_SystemName
Adjusted name of the lock.
CInterProcessLock resource_type
void Lock(const CTimeout &timeout=CTimeout(CTimeout::eInfinite), const CTimeout &granularity=CTimeout(CTimeout::eInfinite))
int TLockHandle
OS-specific lock handle.
void operator()(resource_type &resource) const
string m_Name
Original name of the lock.
const string & GetName(void) const
Get the original name of the lock – exactly as it was specified in the constructor.
NCBI_EXCEPTION_DEFAULT(CInterProcessLockException, CCoreException)
@ eUnlockError
Cannot release the lock.
@ eLockError
Cannot acquire a lock (not eLockTimeout, eCreateError)
@ eNameError
Incorrect name for a lock.
@ eLockTimeout
The lock could not be acquired in the time allotted.
@ eMultipleLocks
Attempt to lock already locked object in the same process.
@ eCreateError
Cannot create the lock object in the OS.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
@ eInfinite
Infinite timeout.
Definition: ncbitime.hpp:1699
#define NCBI_XNCBI_EXPORT
Definition: ncbi_export.h:1283
#define HANDLE
An abstraction for a file handle.
Definition: mdb.c:383
Defines: CTimeFormat - storage class for time format.
Modified on Tue May 28 05:54:23 2024 by modify_doxy.py rev. 669887