BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslmt_mutex.h
Go to the documentation of this file.
1/// @file bslmt_mutex.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_mutex.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_MUTEX
9#define INCLUDED_BSLMT_MUTEX
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_mutex bslmt_mutex
15/// @brief Provide a platform-independent mutex.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_mutex
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_mutex-purpose"> Purpose</a>
25/// * <a href="#bslmt_mutex-classes"> Classes </a>
26/// * <a href="#bslmt_mutex-description"> Description </a>
27/// * <a href="#bslmt_mutex-usage"> Usage </a>
28/// * <a href="#bslmt_mutex-example-1-basic-usage"> Example 1: Basic Usage </a>
29///
30/// # Purpose {#bslmt_mutex-purpose}
31/// Provide a platform-independent mutex.
32///
33/// # Classes {#bslmt_mutex-classes}
34///
35/// - bslmt::Mutex: platform-independent mutex
36///
37/// @see bslmt_recursivemutex, bslmt_mutex
38///
39/// # Description {#bslmt_mutex-description}
40/// This component provides a mutually exclusive lock primitive
41/// ("mutex") by wrapping a suitable platform-specific mechanism. The
42/// `bslmt::Mutex` class provides the following operations: `lock`, `tryLock`,
43/// and `unlock`.
44///
45/// The behavior is undefined if `unlock` is invoked on a `bslmt::Mutex` object
46/// from a thread that did not successfully acquire the lock, or if `lock` is
47/// called twice in a thread without calling `unlock` in between (i.e.,
48/// `bslmt::Mutex` is non-recursive). In particular, `lock` *may* or *may*
49/// *not* deadlock if the current thread holds the lock.
50///
51/// ## Usage {#bslmt_mutex-usage}
52///
53///
54/// This section illustrates intended use of this component.
55///
56/// ### Example 1: Basic Usage {#bslmt_mutex-example-1-basic-usage}
57///
58///
59/// The following snippets of code illustrate the use of `bslmt::Mutex` to write
60/// a thread-safe class, `my_SafeAccount`, given a thread-unsafe class,
61/// `my_Account`. The simple `my_Account` class is defined as follows:
62/// @code
63/// /// This `class` represents a bank account with a single balance. It
64/// /// is not thread-safe.
65/// class my_Account {
66///
67/// // DATA
68/// double d_money; // amount of money in the account
69///
70/// public:
71/// // CREATORS
72///
73/// /// Create an account with zero balance.
74/// my_Account();
75///
76/// /// Create an account having the value of the specified `original`
77/// /// account.
78/// my_Account(const my_Account& original);
79///
80/// /// Destroy this account.
81/// ~my_Account();
82///
83/// // MANIPULATORS
84///
85/// /// Assign to this account the value of the specified `rhs` account,
86/// /// and return a reference to this modifiable account.
87/// my_Account& operator=(const my_Account& rhs);
88///
89/// /// Deposit the specified `amount` of money into this account.
90/// void deposit(double amount);
91///
92/// /// Withdraw the specified `amount` of money from this account.
93/// void withdraw(double amount);
94///
95/// // ACCESSORS
96///
97/// /// Return the amount of money that is available for withdrawal
98/// /// from this account.
99/// double balance() const;
100/// };
101///
102/// // CREATORS
103/// my_Account::my_Account()
104/// : d_money(0.0)
105/// {
106/// }
107///
108/// my_Account::my_Account(const my_Account& original)
109/// : d_money(original.d_money)
110/// {
111/// }
112///
113/// my_Account::~my_Account()
114/// {
115/// }
116///
117/// // MANIPULATORS
118/// my_Account& my_Account::operator=(const my_Account& rhs)
119/// {
120/// d_money = rhs.d_money;
121/// return *this;
122/// }
123///
124/// void my_Account::deposit(double amount)
125/// {
126/// d_money += amount;
127/// }
128///
129/// void my_Account::withdraw(double amount)
130/// {
131/// d_money -= amount;
132/// }
133///
134/// // ACCESSORS
135/// double my_Account::balance() const
136/// {
137/// return d_money;
138/// }
139/// @endcode
140/// Next, we use a `bslmt::Mutex` object to render atomic the function calls of
141/// a new thread-safe class that uses the thread-unsafe class in its
142/// implementation. Note the typical use of `mutable` for the lock:
143/// @code
144/// /// This `class` provides a thread-safe handle to an account (held, not
145/// /// owned) passed at construction.
146/// class my_SafeAccountHandle {
147///
148/// // DATA
149/// my_Account *d_account_p; // held, not owned
150/// mutable bslmt::Mutex d_lock; // guard access to `d_account_p`
151///
152/// private:
153/// // NOT IMPLEMENTED
154/// my_SafeAccountHandle(const my_SafeAccountHandle&);
155/// my_SafeAccountHandle& operator=(const my_SafeAccountHandle&);
156///
157/// public:
158/// // CREATORS
159///
160/// /// Create a thread-safe handle to the specified `account`.
161/// my_SafeAccountHandle(my_Account *account);
162///
163/// /// Destroy this handle. Note that the held account is unaffected
164/// /// by this operation.
165/// ~my_SafeAccountHandle();
166///
167/// // MANIPULATORS
168///
169/// /// Atomically deposit the specified `amount` of money into the
170/// /// account held by this handle. Note that this operation is
171/// /// thread-safe; no `lock` is needed.
172/// void deposit(double amount);
173///
174/// /// Provide exclusive access to the underlying account held by this
175/// /// object.
176/// void lock();
177///
178/// /// Release exclusivity of the access to the underlying account held
179/// /// by this object.
180/// void unlock();
181///
182/// /// Atomically withdraw the specified `amount` of money from the
183/// /// account held by this handle. Note that this operation is
184/// /// thread-safe; no `lock` is needed.
185/// void withdraw(double amount);
186///
187/// // ACCESSORS
188///
189/// /// Return the address of the modifiable account held by this
190/// /// handle.
191/// my_Account *account() const;
192///
193/// /// Atomically return the amount of money that is available for
194/// /// withdrawal from the account held by this handle.
195/// double balance() const;
196/// };
197/// @endcode
198/// The implementation show-casing the use of `bslmt::Mutex` follows:
199/// @code
200/// // CREATORS
201/// my_SafeAccountHandle::my_SafeAccountHandle(my_Account *account)
202/// : d_account_p(account)
203/// {
204/// }
205///
206/// my_SafeAccountHandle::~my_SafeAccountHandle()
207/// {
208/// }
209///
210/// // MANIPULATORS
211/// void my_SafeAccountHandle::deposit(double amount)
212/// {
213/// @endcode
214/// Where appropriate, clients should use a lock-guard to ensure that an
215/// acquired mutex is always properly released, even if an exception is thrown.
216/// See @ref bslmt_lockguard for more information:
217/// @code
218/// d_lock.lock(); // consider using 'bslmt::LockGuard'
219/// d_account_p->deposit(amount);
220/// d_lock.unlock();
221/// }
222///
223/// void my_SafeAccountHandle::lock()
224/// {
225/// d_lock.lock();
226/// }
227///
228/// void my_SafeAccountHandle::unlock()
229/// {
230/// d_lock.unlock();
231/// }
232///
233/// void my_SafeAccountHandle::withdraw(double amount)
234/// {
235/// d_lock.lock(); // consider using 'bslmt::LockGuard'
236/// d_account_p->withdraw(amount);
237/// d_lock.unlock();
238/// }
239///
240/// // ACCESSORS
241/// my_Account *my_SafeAccountHandle::account() const
242/// {
243/// return d_account_p;
244/// }
245///
246/// double my_SafeAccountHandle::balance() const
247/// {
248/// d_lock.lock(); // consider using 'bslmt::LockGuard'
249/// const double res = d_account_p->balance();
250/// d_lock.unlock();
251/// return res;
252/// }
253/// @endcode
254/// The handle's atomic methods are used just as the corresponding methods in
255/// `my_Account`:
256/// @code
257/// my_Account account;
258/// account.deposit(100.50);
259/// double paycheck = 50.25;
260/// my_SafeAccountHandle handle(&account);
261///
262/// assert(100.50 == handle.balance());
263/// handle.deposit(paycheck); assert(150.75 == handle.balance());
264/// @endcode
265/// We can also use the handle's `lock` and `unlock` methods to implement
266/// non-primitive atomic transactions on the account:
267/// @code
268/// double check[5] = { 25.0, 100.0, 99.95, 75.0, 50.0 };
269///
270/// handle.lock(); // consider using 'bslmt::LockGuard'
271///
272/// double originalBalance = handle.account()->balance();
273/// for (int i = 0; i < 5; ++i) {
274/// handle.account()->deposit(check[i]);
275/// }
276/// assert(originalBalance + 349.95 == handle.account()->balance());
277/// handle.unlock();
278/// @endcode
279/// @}
280/** @} */
281/** @} */
282
283/** @addtogroup bsl
284 * @{
285 */
286/** @addtogroup bslmt
287 * @{
288 */
289/** @addtogroup bslmt_mutex
290 * @{
291 */
292
293#include <bslscm_version.h>
294
297#include <bslmt_platform.h>
298
299
300namespace bslmt {
301
302template <class THREAD_POLICY>
304
305 // ===========
306 // class Mutex
307 // ===========
308
309/// This `class` implements a lightweight, portable wrapper of an OS-level
310/// mutex lock to support intra-process synchronization.
311///
312/// \pre The behavior is undefined if the `lock` method of this class is invoked more than once
313/// on the same mutex object in the same thread without an intervening call
314/// to `unLock`.
315///
316/// See @ref bslmt_mutex
317class Mutex {
318
319 // DATA
320 MutexImpl<Platform::ThreadPolicy> d_imp; // platform-specific
321 // implementation
322
323 private:
324 // NOT IMPLEMENTED
325 Mutex(const Mutex&);
326 Mutex& operator=(const Mutex&);
327
328 public:
329 // PUBLIC TYPES
330
331 /// `NativeType` is an alias for the underlying OS-level mutex type. It
332 /// is exposed so that other `bslmt` components can operate directly on
333 /// this mutex.
335
336 // CREATORS
337
338 /// Create a mutex object in the unlocked state. This method does not
339 /// return normally unless there are sufficient system resources to
340 /// construct the object.
341 Mutex();
342
343 /// Destroy this mutex object.
344 /// \pre The behavior is undefined if the mutex
345 /// is in a locked state.
346 ~Mutex();
347
348 // MANIPULATORS
349
350 /// Acquire a lock on this mutex object. If this object is currently
351 /// locked by a different thread, then suspend execution of the current thread until a lock can be acquired.
352 ///
353 /// \pre The behavior is undefined if
354 /// the calling thread already owns the lock on this mutex, and may
355 /// result in deadlock.
356 void lock();
357
358 /// Return a reference to the modifiable OS-level mutex underlying this
359 /// object. This method is intended only to support other `bslmt`
360 /// components that must operate directly on this mutex.
362
363 /// Attempt to acquire a lock on this mutex object. Return 0 on
364 /// success, and a non-zero value if this object is already locked by a different thread.
365 ///
366 /// \pre The behavior is undefined if the calling thread
367 /// already owns the lock on this mutex, and may result in deadlock.
368 int tryLock();
369
370 /// Release a lock on this mutex that was previously acquired through a
371 /// call to `lock`, or a successful call to `tryLock`, enabling another
372 /// thread to acquire a lock on this mutex.
373 ///
374 /// \pre The behavior is undefined unless the calling thread currently owns the lock on this mutex.
375 void unlock();
376};
377
378// ============================================================================
379// INLINE DEFINITIONS
380// ============================================================================
381
382 // -----------
383 // class Mutex
384 // -----------
385
386// CREATORS
387inline
389{
390}
391
392inline
394{
395}
396
397// MANIPULATORS
398inline
400{
401 d_imp.lock();
402}
403
404inline
406{
407 return d_imp.nativeMutex();
408}
409
410inline
412{
413 return d_imp.tryLock();
414}
415
416inline
418{
419 d_imp.unlock();
420}
421
422} // close package namespace
423
424
425#endif
426
427// ----------------------------------------------------------------------------
428// Copyright 2023 Bloomberg Finance L.P.
429//
430// Licensed under the Apache License, Version 2.0 (the "License");
431// you may not use this file except in compliance with the License.
432// You may obtain a copy of the License at
433//
434// http://www.apache.org/licenses/LICENSE-2.0
435//
436// Unless required by applicable law or agreed to in writing, software
437// distributed under the License is distributed on an "AS IS" BASIS,
438// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
439// See the License for the specific language governing permissions and
440// limitations under the License.
441// ----------------------------- END-OF-FILE ----------------------------------
442
443/** @} */
444/** @} */
445/** @} */
Definition bslmt_mutex.h:303
Definition bslmt_mutex.h:317
MutexImpl< Platform::ThreadPolicy >::NativeType NativeType
Definition bslmt_mutex.h:334
void lock()
Definition bslmt_mutex.h:399
NativeType & nativeMutex()
Definition bslmt_mutex.h:405
int tryLock()
Definition bslmt_mutex.h:411
Mutex()
Definition bslmt_mutex.h:388
~Mutex()
Definition bslmt_mutex.h:393
void unlock()
Definition bslmt_mutex.h:417
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bslmt_barrier.h:344