BDE 4.14.0 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/// // NOT IMPLEMENTED
153/// my_SafeAccountHandle(const my_SafeAccountHandle&);
154/// my_SafeAccountHandle& operator=(const my_SafeAccountHandle&);
155///
156/// public:
157/// // CREATORS
158///
159/// /// Create a thread-safe handle to the specified `account`.
160/// my_SafeAccountHandle(my_Account *account);
161///
162/// /// Destroy this handle. Note that the held account is unaffected
163/// /// by this operation.
164/// ~my_SafeAccountHandle();
165///
166/// // MANIPULATORS
167///
168/// /// Atomically deposit the specified `amount` of money into the
169/// /// account held by this handle. Note that this operation is
170/// /// thread-safe; no `lock` is needed.
171/// void deposit(double amount);
172///
173/// /// Provide exclusive access to the underlying account held by this
174/// /// object.
175/// void lock();
176///
177/// /// Release exclusivity of the access to the underlying account held
178/// /// by this object.
179/// void unlock();
180///
181/// /// Atomically withdraw the specified `amount` of money from the
182/// /// account held by this handle. Note that this operation is
183/// /// thread-safe; no `lock` is needed.
184/// void withdraw(double amount);
185///
186/// // ACCESSORS
187///
188/// /// Return the address of the modifiable account held by this
189/// /// handle.
190/// my_Account *account() const;
191///
192/// /// Atomically return the amount of money that is available for
193/// /// withdrawal from the account held by this handle.
194/// double balance() const;
195/// };
196/// @endcode
197/// The implementation show-casing the use of `bslmt::Mutex` follows:
198/// @code
199/// // CREATORS
200/// my_SafeAccountHandle::my_SafeAccountHandle(my_Account *account)
201/// : d_account_p(account)
202/// {
203/// }
204///
205/// my_SafeAccountHandle::~my_SafeAccountHandle()
206/// {
207/// }
208///
209/// // MANIPULATORS
210/// void my_SafeAccountHandle::deposit(double amount)
211/// {
212/// @endcode
213/// Where appropriate, clients should use a lock-guard to ensure that an
214/// acquired mutex is always properly released, even if an exception is thrown.
215/// See @ref bslmt_lockguard for more information:
216/// @code
217/// d_lock.lock(); // consider using 'bslmt::LockGuard'
218/// d_account_p->deposit(amount);
219/// d_lock.unlock();
220/// }
221///
222/// void my_SafeAccountHandle::lock()
223/// {
224/// d_lock.lock();
225/// }
226///
227/// void my_SafeAccountHandle::unlock()
228/// {
229/// d_lock.unlock();
230/// }
231///
232/// void my_SafeAccountHandle::withdraw(double amount)
233/// {
234/// d_lock.lock(); // consider using 'bslmt::LockGuard'
235/// d_account_p->withdraw(amount);
236/// d_lock.unlock();
237/// }
238///
239/// // ACCESSORS
240/// my_Account *my_SafeAccountHandle::account() const
241/// {
242/// return d_account_p;
243/// }
244///
245/// double my_SafeAccountHandle::balance() const
246/// {
247/// d_lock.lock(); // consider using 'bslmt::LockGuard'
248/// const double res = d_account_p->balance();
249/// d_lock.unlock();
250/// return res;
251/// }
252/// @endcode
253/// The handle's atomic methods are used just as the corresponding methods in
254/// `my_Account`:
255/// @code
256/// my_Account account;
257/// account.deposit(100.50);
258/// double paycheck = 50.25;
259/// my_SafeAccountHandle handle(&account);
260///
261/// assert(100.50 == handle.balance());
262/// handle.deposit(paycheck); assert(150.75 == handle.balance());
263/// @endcode
264/// We can also use the handle's `lock` and `unlock` methods to implement
265/// non-primitive atomic transactions on the account:
266/// @code
267/// double check[5] = { 25.0, 100.0, 99.95, 75.0, 50.0 };
268///
269/// handle.lock(); // consider using 'bslmt::LockGuard'
270///
271/// double originalBalance = handle.account()->balance();
272/// for (int i = 0; i < 5; ++i) {
273/// handle.account()->deposit(check[i]);
274/// }
275/// assert(originalBalance + 349.95 == handle.account()->balance());
276/// handle.unlock();
277/// @endcode
278/// @}
279/** @} */
280/** @} */
281
282/** @addtogroup bsl
283 * @{
284 */
285/** @addtogroup bslmt
286 * @{
287 */
288/** @addtogroup bslmt_mutex
289 * @{
290 */
291
292#include <bslscm_version.h>
293
296#include <bslmt_platform.h>
297
298
299namespace bslmt {
300
301template <class THREAD_POLICY>
303
304 // ===========
305 // class Mutex
306 // ===========
307
308/// This `class` implements a lightweight, portable wrapper of an OS-level
309/// mutex lock to support intra-process synchronization. The behavior is
310/// undefined if the `lock` method of this class is invoked more than once
311/// on the same mutex object in the same thread without an intervening call
312/// to `unLock`.
313///
314/// See @ref bslmt_mutex
315class Mutex {
316
317 // DATA
318 MutexImpl<Platform::ThreadPolicy> d_imp; // platform-specific
319 // implementation
320
321 // NOT IMPLEMENTED
322 Mutex(const Mutex&);
323 Mutex& operator=(const Mutex&);
324
325 public:
326 // PUBLIC TYPES
327
328 /// `NativeType` is an alias for the underlying OS-level mutex type. It
329 /// is exposed so that other `bslmt` components can operate directly on
330 /// this mutex.
332
333 // CREATORS
334
335 /// Create a mutex object in the unlocked state. This method does not
336 /// return normally unless there are sufficient system resources to
337 /// construct the object.
338 Mutex();
339
340 /// Destroy this mutex object. The behavior is undefined if the mutex
341 /// is in a locked state.
342 ~Mutex();
343
344 // MANIPULATORS
345
346 /// Acquire a lock on this mutex object. If this object is currently
347 /// locked by a different thread, then suspend execution of the current
348 /// thread until a lock can be acquired. The behavior is undefined if
349 /// the calling thread already owns the lock on this mutex, and may
350 /// result in deadlock.
351 void lock();
352
353 /// Return a reference to the modifiable OS-level mutex underlying this
354 /// object. This method is intended only to support other `bslmt`
355 /// components that must operate directly on this mutex.
357
358 /// Attempt to acquire a lock on this mutex object. Return 0 on
359 /// success, and a non-zero value if this object is already locked by a
360 /// different thread. The behavior is undefined if the calling thread
361 /// already owns the lock on this mutex, and may result in deadlock.
362 int tryLock();
363
364 /// Release a lock on this mutex that was previously acquired through a
365 /// call to `lock`, or a successful call to `tryLock`, enabling another
366 /// thread to acquire a lock on this mutex. The behavior is undefined
367 /// unless the calling thread currently owns the lock on this mutex.
368 void unlock();
369};
370
371// ============================================================================
372// INLINE DEFINITIONS
373// ============================================================================
374
375 // -----------
376 // class Mutex
377 // -----------
378
379// CREATORS
380inline
382{
383}
384
385inline
387{
388}
389
390// MANIPULATORS
391inline
393{
394 d_imp.lock();
395}
396
397inline
399{
400 return d_imp.nativeMutex();
401}
402
403inline
405{
406 return d_imp.tryLock();
407}
408
409inline
411{
412 d_imp.unlock();
413}
414
415} // close package namespace
416
417
418#endif
419
420// ----------------------------------------------------------------------------
421// Copyright 2023 Bloomberg Finance L.P.
422//
423// Licensed under the Apache License, Version 2.0 (the "License");
424// you may not use this file except in compliance with the License.
425// You may obtain a copy of the License at
426//
427// http://www.apache.org/licenses/LICENSE-2.0
428//
429// Unless required by applicable law or agreed to in writing, software
430// distributed under the License is distributed on an "AS IS" BASIS,
431// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
432// See the License for the specific language governing permissions and
433// limitations under the License.
434// ----------------------------- END-OF-FILE ----------------------------------
435
436/** @} */
437/** @} */
438/** @} */
Definition bslmt_mutex.h:302
Definition bslmt_mutex.h:315
MutexImpl< Platform::ThreadPolicy >::NativeType NativeType
Definition bslmt_mutex.h:331
void lock()
Definition bslmt_mutex.h:392
NativeType & nativeMutex()
Definition bslmt_mutex.h:398
int tryLock()
Definition bslmt_mutex.h:404
Mutex()
Definition bslmt_mutex.h:381
~Mutex()
Definition bslmt_mutex.h:386
void unlock()
Definition bslmt_mutex.h:410
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bslmt_barrier.h:344