BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bsls_bsllock.h
Go to the documentation of this file.
1/// @file bsls_bsllock.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_bsllock.h -*-C++-*-
8#ifndef INCLUDED_BSLS_BSLLOCK
9#define INCLUDED_BSLS_BSLLOCK
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_bsllock bsls_bsllock
15/// @brief Provide a platform-independent mutex for use below `bslmt`.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_bsllock
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_bsllock-purpose"> Purpose</a>
25/// * <a href="#bsls_bsllock-classes"> Classes </a>
26/// * <a href="#bsls_bsllock-description"> Description </a>
27/// * <a href="#bsls_bsllock-usage"> Usage </a>
28/// * <a href="#bsls_bsllock-example-1-using-bsls-bsllock-to-make-a-class-thread-safe"> Example 1: Using bsls::BslLock to Make a class Thread-Safe </a>
29///
30/// # Purpose {#bsls_bsllock-purpose}
31/// Provide a platform-independent mutex for use below `bslmt`.
32///
33/// # Classes {#bsls_bsllock-classes}
34///
35/// - bsls::BslLock: platform-independent mutex
36/// - bsls::BslLockGuard: RAII mechanism for locking/unlocking a `BslLock`
37///
38/// @see bslmt_mutex
39///
40/// # Description {#bsls_bsllock-description}
41/// This component provides a mutually exclusive lock primitive
42/// ("mutex") by wrapping a suitable platform-specific mechanism. The
43/// `bsls::BslLock` class provides `lock` and `unlock` operations. Note that
44/// `bsls::BslLock` is not intended for direct client use; see @ref bslmt_mutex
45/// instead. Also note that `bsls::BslLock` is not recursive.
46///
47/// This component also provides the `bsls::BslLockGuard` class, a mechanism
48/// that follows the RAII idiom for automatically acquiring and releasing the
49/// lock on an associated `bsls::BslLock` object. To ensure exception safety,
50/// client code should make use of a `bsls::BslLockGuard` object wherever
51/// appropriate rather than calling the methods on the associated
52/// `bsls::BslLock` object directly.
53///
54/// ## Usage {#bsls_bsllock-usage}
55///
56///
57/// In this section we show intended use of this component.
58///
59/// ### Example 1: Using bsls::BslLock to Make a class Thread-Safe {#bsls_bsllock-example-1-using-bsls-bsllock-to-make-a-class-thread-safe}
60///
61///
62/// In this example we illustrate the use of `bsls::BslLock` and
63/// `bsls::BslLockGuard` to write a thread-safe class.
64///
65/// First, we provide an elided definition of the `my_Account` class. Note the
66/// `d_lock` data member of type `bsls::BslLock`:
67/// @code
68/// class my_Account {
69/// // This 'class' implements a very simplistic bank account. It is meant
70/// // for illustrative purposes only.
71///
72/// // DATA
73/// double d_money; // amount of money in the account
74/// mutable bsls::BslLock d_lock; // ensure exclusive access to 'd_money'
75///
76/// // ...
77///
78/// public:
79///
80/// // ...
81///
82/// // MANIPULATORS
83/// void deposit(double amount);
84/// // Atomically deposit the specified 'amount' of money into this
85/// // account. The behavior is undefined unless 'amount >= 0.0'.
86///
87/// int withdraw(double amount);
88/// // Atomically withdraw the specified 'amount' of money from this
89/// // account. Return 0 on success, and a non-zero value otherwise.
90/// // The behavior is undefined unless 'amount >= 0.0'.
91///
92/// // ...
93/// };
94/// @endcode
95/// Next, we show the implementation of the two `my_Account` manipulators
96/// show-casing the use of `bsls::BslLock` and `bsls::BslLockGuard`:
97/// @code
98/// // MANIPULATORS
99/// void my_Account::deposit(double amount)
100/// {
101/// @endcode
102/// Here, we use the interface of `bsls::BslLock` directly. However, wherever
103/// appropriate, a `bsls::BslLockGuard` object should be used instead to ensure
104/// that an acquired lock is always properly released, even if an exception is
105/// thrown:
106/// @code
107/// d_lock.lock(); // consider using 'bsls::BslLockGuard' (see 'withdraw')
108/// d_money += amount;
109/// d_lock.unlock();
110/// }
111/// @endcode
112/// In contrast, `withdraw` uses a `bsls::BslLockGuard` to automatically acquire
113/// and release the lock. The lock is acquired as a side-effect of the
114/// construction of `guard`, and released when `guard` is destroyed upon
115/// returning from the function:
116/// @code
117/// int my_Account::withdraw(double amount)
118/// {
119/// bsls::BslLockGuard guard(&d_lock); // a very good practice
120///
121/// if (amount <= d_money) {
122/// d_money -= amount;
123/// return 0;
124/// }
125/// else {
126/// return -1;
127/// }
128/// }
129/// @endcode
130/// @}
131/** @} */
132/** @} */
133
134/** @addtogroup bsl
135 * @{
136 */
137/** @addtogroup bsls
138 * @{
139 */
140/** @addtogroup bsls_bsllock
141 * @{
142 */
143
144#include <bsls_platform.h>
145
146#ifdef BSLS_PLATFORM_OS_WINDOWS
148#else
150#endif
151
152#ifdef BDE_BUILD_TARGET_SAFE
153// This component needs to be below bsls_assert in the physical hierarchy, so
154// 'BSLS_ASSERT' macros can't be used here. To workaround this issue, we use
155// the C 'assert' instead.
156#include <assert.h>
157#define BSLS_BSLLOCK_ASSERT_SAFE(x) assert((x))
158#else
159#define BSLS_BSLLOCK_ASSERT_SAFE(x)
160#endif
161
162
163namespace bsls {
164
165 // =============
166 // class BslLock
167 // =============
168
169/// This `class` implements a light-weight, portable wrapper of an OS-level
170/// mutex to support intra-process synchronization. The mutex implemented by this class is *non*-recursive.
171///
172/// \note Note that `BslLock` is *not* intended
173/// for direct use by client code; it is meant for internal use only.
174///
175/// See @ref bsls_bsllock
176class BslLock {
177
178 // DATA
179#ifdef BSLS_PLATFORM_OS_WINDOWS
180 BslLockImpl_win32 d_lock; // Windows critical section
181#else
182 BslLockImpl_pthread d_lock; // 'pthreads' mutex object
183#endif
184
185 private:
186 // NOT IMPLEMENTED
187 BslLock(const BslLock&); // = delete
188 BslLock& operator=(const BslLock&); // = delete
189
190 public:
191 // CREATORS
192
193 /// Create a lock object initialized to the unlocked state.
194 BslLock();
195
196 /// Destroy this lock object.
197 /// \pre The behavior is undefined unless this
198 /// object is in the unlocked state.
199 ~BslLock();
200
201 // MANIPULATORS
202
203 /// Acquire the lock on this object. If the lock on this object is
204 /// currently held by another thread, then suspend execution of the
205 /// calling thread until the lock can be acquired.
206 ///
207 /// \pre The behavior is undefined unless the calling thread does not already hold the lock on this object.
208 ///
209 /// \note Note that deadlock may result if this method is
210 /// invoked while the calling thread holds the lock on the object.
211 void lock();
212
213 /// Release the lock on this object that was previously acquired through
214 /// a call to `lock`, enabling another thread to acquire the lock.
215 ///
216 /// \pre The behavior is undefined unless the calling thread holds the lock on
217 /// this object.
218 void unlock();
219};
220
221 // ==================
222 // class BslLockGuard
223 // ==================
224
225/// This `class` implements a guard for automatically acquiring and
226/// releasing the lock on an associated `bsls::BslLock` object. This
227/// mechanism follows the RAII idiom whereby the lock on the `BslLock`
228/// associated with a guard object is acquired upon construction and
229/// released upon destruction.
230///
231/// See @ref bsls_bsllock
233
234 // DATA
235 BslLock *d_lock_p; // lock guarded by this object (held, not owned)
236
237 private:
238 // NOT IMPLEMENTED
239 BslLockGuard(const BslLockGuard&); // = delete
240 BslLockGuard& operator=(const BslLockGuard&); // = delete
241
242 public:
243 // CREATORS
244
245 /// Create a guard object that conditionally manages the specified
246 /// `lock`, and acquires the lock on `lock` by invoking its `lock` method.
247 ///
248 /// \pre The behavior is undefined unless the calling thread does not already hold the lock on `lock`.
249 ///
250 /// \note Note that deadlock may result
251 /// if a guard is created for `lock` while the calling thread holds the
252 /// lock on `lock`. Also note that `lock` must remain valid throughout
253 /// the lifetime of this guard, or until `release` is called.
254 explicit BslLockGuard(BslLock *lock);
255
256 /// Destroy this guard object and release the lock on the object it
257 /// manages (if any) by invoking the `unlock` method of the object that
258 /// was supplied at construction of this guard. If no lock is currently being managed, this method has no effect.
259 ///
260 /// \note Note that if this guard
261 /// object currently manages a lock, this method assumes the behavior of
262 /// `BslLock::unlock`.
264
265 // MANIPULATORS
266
267 /// Release from management, with no effect, the object currently managed by this guard, if any.
268 ///
269 /// \note Note that `unlock` is *not* called
270 /// on the managed object upon its release.
271 void release();
272};
273
274// ============================================================================
275// INLINE FUNCTION DEFINITIONS
276// ============================================================================
277
278 // -------------
279 // class BslLock
280 // -------------
281
282// CREATORS
283inline
287
288inline
292
293// MANIPULATORS
294inline
296{
297 d_lock.lock();
298}
299
300inline
302{
303 d_lock.unlock();
304}
305
306 // ------------------
307 // class BslLockGuard
308 // ------------------
309
310// CREATORS
311inline
312BslLockGuard::BslLockGuard(BslLock *lock)
313: d_lock_p(lock)
314{
316 d_lock_p->lock();
317}
318
319inline
321{
322 if (d_lock_p) {
323 d_lock_p->unlock();
324 }
325}
326
327// MANIPULATORS
328inline
330{
331 d_lock_p = 0;
332}
333
334} // close package namespace
335
336
337#endif
338
339// ----------------------------------------------------------------------------
340// Copyright 2018 Bloomberg Finance L.P.
341//
342// Licensed under the Apache License, Version 2.0 (the "License");
343// you may not use this file except in compliance with the License.
344// You may obtain a copy of the License at
345//
346// http://www.apache.org/licenses/LICENSE-2.0
347//
348// Unless required by applicable law or agreed to in writing, software
349// distributed under the License is distributed on an "AS IS" BASIS,
350// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
351// See the License for the specific language governing permissions and
352// limitations under the License.
353// ----------------------------- END-OF-FILE ----------------------------------
354
355/** @} */
356/** @} */
357/** @} */
Definition bsls_bsllock.h:232
void release()
Definition bsls_bsllock.h:329
~BslLockGuard()
Definition bsls_bsllock.h:320
Definition bsls_bsllock.h:176
void lock()
Definition bsls_bsllock.h:295
void unlock()
Definition bsls_bsllock.h:301
BslLock()
Create a lock object initialized to the unlocked state.
Definition bsls_bsllock.h:284
~BslLock()
Definition bsls_bsllock.h:289
#define BSLS_BSLLOCK_ASSERT_SAFE(x)
Definition bsls_bsllock.h:159
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlt_iso8601util.h:707