BDE 4.14.0 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
171/// by this class is *non*-recursive. Note that `BslLock` is *not* intended
172/// for direct use by client code; it is meant for internal use only.
173///
174/// See @ref bsls_bsllock
175class BslLock {
176
177 // DATA
178#ifdef BSLS_PLATFORM_OS_WINDOWS
179 BslLockImpl_win32 d_lock; // Windows critical section
180#else
181 BslLockImpl_pthread d_lock; // 'pthreads' mutex object
182#endif
183
184 private:
185 // NOT IMPLEMENTED
186 BslLock(const BslLock&); // = delete
187 BslLock& operator=(const BslLock&); // = delete
188
189 public:
190 // CREATORS
191
192 /// Create a lock object initialized to the unlocked state.
193 BslLock();
194
195 /// Destroy this lock object. The behavior is undefined unless this
196 /// object is in the unlocked state.
197 ~BslLock();
198
199 // MANIPULATORS
200
201 /// Acquire the lock on this object. If the lock on this object is
202 /// currently held by another thread, then suspend execution of the
203 /// calling thread until the lock can be acquired. The behavior is
204 /// undefined unless the calling thread does not already hold the lock
205 /// on this object. Note that deadlock may result if this method is
206 /// invoked while the calling thread holds the lock on the object.
207 void lock();
208
209 /// Release the lock on this object that was previously acquired through
210 /// a call to `lock`, enabling another thread to acquire the lock. The
211 /// behavior is undefined unless the calling thread holds the lock on
212 /// this object.
213 void unlock();
214};
215
216 // ==================
217 // class BslLockGuard
218 // ==================
219
220/// This `class` implements a guard for automatically acquiring and
221/// releasing the lock on an associated `bsls::BslLock` object. This
222/// mechanism follows the RAII idiom whereby the lock on the `BslLock`
223/// associated with a guard object is acquired upon construction and
224/// released upon destruction.
225///
226/// See @ref bsls_bsllock
228
229 // DATA
230 BslLock *d_lock_p; // lock guarded by this object (held, not owned)
231
232 private:
233 // NOT IMPLEMENTED
234 BslLockGuard(const BslLockGuard&); // = delete
235 BslLockGuard& operator=(const BslLockGuard&); // = delete
236
237 public:
238 // CREATORS
239
240 /// Create a guard object that conditionally manages the specified
241 /// `lock`, and acquires the lock on `lock` by invoking its `lock`
242 /// method. The behavior is undefined unless the calling thread does
243 /// not already hold the lock on `lock`. Note that deadlock may result
244 /// if a guard is created for `lock` while the calling thread holds the
245 /// lock on `lock`. Also note that `lock` must remain valid throughout
246 /// the lifetime of this guard, or until `release` is called.
247 explicit BslLockGuard(BslLock *lock);
248
249 /// Destroy this guard object and release the lock on the object it
250 /// manages (if any) by invoking the `unlock` method of the object that
251 /// was supplied at construction of this guard. If no lock is currently
252 /// being managed, this method has no effect. Note that if this guard
253 /// object currently manages a lock, this method assumes the behavior of
254 /// `BslLock::unlock`.
256
257 // MANIPULATORS
258
259 /// Release from management, with no effect, the object currently
260 /// managed by this guard, if any. Note that `unlock` is *not* called
261 /// on the managed object upon its release.
262 void release();
263};
264
265// ============================================================================
266// INLINE FUNCTION DEFINITIONS
267// ============================================================================
268
269 // -------------
270 // class BslLock
271 // -------------
272
273// CREATORS
274inline
278
279inline
283
284// MANIPULATORS
285inline
287{
288 d_lock.lock();
289}
290
291inline
293{
294 d_lock.unlock();
295}
296
297 // ------------------
298 // class BslLockGuard
299 // ------------------
300
301// CREATORS
302inline
303BslLockGuard::BslLockGuard(BslLock *lock)
304: d_lock_p(lock)
305{
307 d_lock_p->lock();
308}
309
310inline
312{
313 if (d_lock_p) {
314 d_lock_p->unlock();
315 }
316}
317
318// MANIPULATORS
319inline
321{
322 d_lock_p = 0;
323}
324
325} // close package namespace
326
327
328#endif
329
330// ----------------------------------------------------------------------------
331// Copyright 2018 Bloomberg Finance L.P.
332//
333// Licensed under the Apache License, Version 2.0 (the "License");
334// you may not use this file except in compliance with the License.
335// You may obtain a copy of the License at
336//
337// http://www.apache.org/licenses/LICENSE-2.0
338//
339// Unless required by applicable law or agreed to in writing, software
340// distributed under the License is distributed on an "AS IS" BASIS,
341// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
342// See the License for the specific language governing permissions and
343// limitations under the License.
344// ----------------------------- END-OF-FILE ----------------------------------
345
346/** @} */
347/** @} */
348/** @} */
Definition bsls_bsllock.h:227
void release()
Definition bsls_bsllock.h:320
~BslLockGuard()
Definition bsls_bsllock.h:311
Definition bsls_bsllock.h:175
void lock()
Definition bsls_bsllock.h:286
void unlock()
Definition bsls_bsllock.h:292
BslLock()
Create a lock object initialized to the unlocked state.
Definition bsls_bsllock.h:275
~BslLock()
Definition bsls_bsllock.h:280
#define BSLS_BSLLOCK_ASSERT_SAFE(x)
Definition bsls_bsllock.h:159
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691