BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_readerwriterlockassert.h
Go to the documentation of this file.
1/// @file bslmt_readerwriterlockassert.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_readerwriterlockassert.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_READERWRITERLOCKASSERT
9#define INCLUDED_BSLMT_READERWRITERLOCKASSERT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_readerwriterlockassert bslmt_readerwriterlockassert
15/// @brief Provide an assert macro for verifying reader-writer lock status.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_readerwriterlockassert
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_readerwriterlockassert-purpose"> Purpose</a>
25/// * <a href="#bslmt_readerwriterlockassert-classes"> Classes </a>
26/// * <a href="#bslmt_readerwriterlockassert-macros"> Macros </a>
27/// * <a href="#bslmt_readerwriterlockassert-description"> Description </a>
28/// * <a href="#bslmt_readerwriterlockassert-caveat-false-positives"> Caveat: False Positives </a>
29/// * <a href="#bslmt_readerwriterlockassert-requirements-on-the-lock-type"> Requirements on the Lock Type </a>
30/// * <a href="#bslmt_readerwriterlockassert-usage"> Usage </a>
31/// * <a href="#bslmt_readerwriterlockassert-example-1-checking-consistency-within-private-methods"> Example 1: Checking Consistency Within Private Methods </a>
32///
33/// # Purpose {#bslmt_readerwriterlockassert-purpose}
34/// Provide an assert macro for verifying reader-writer lock status.
35///
36/// # Classes {#bslmt_readerwriterlockassert-classes}
37///
38///
39/// # Macros {#bslmt_readerwriterlockassert-macros}
40///
41/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED: test in non-opt modes
42/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_SAFE: test in safe mode
43/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_OPT: test in all modes
44/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ: test in non-opt modes
45/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE: test in safe mode
46/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT: test in all modes
47/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE: test in non-opt modes
48/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_SAFE: test in safe mode
49/// - BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_OPT: test in all modes
50///
51/// @see bslmt_lockassert, bslmt_readerwriterlock, bslmt_readerwritermutex
52///
53/// # Description {#bslmt_readerwriterlockassert-description}
54/// This component provides macros for asserting that a
55/// reader-writer lock is locked. It does not distinguish between locks held by
56/// the current thread or other threads. If the macro is active in the current
57/// build mode, when the macro is called, if the supplied lock is unlocked, the
58/// assert handler installed for `BSLS_ASSERT` will be called. The assert
59/// handler installed by default will report an error and abort the task. Note
60/// that the type of lock (pointer) passed to each of these macros is determined
61/// at compile-time. See {Requirements on the Lock Type} below.
62///
63/// The nine macros defined by the component are analogous to the macros defined
64/// by `BSLS_ASSERT`:
65/// @code
66/// +---------------------------------------------------+------------------=+
67/// | Macro | When Active |
68/// +===================================================+===================+
69/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED' | When |
70/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ' | 'BSLS_ASSERT' |
71/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE' | is active. |
72/// +---------------------------------------------------+-------------------+
73/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_SAFE' | When |
74/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE' | 'BSLS_ASSERT_SAFE'|
75/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_SAFE'| is active. |
76/// +---------------------------------------------------+-------------------+
77/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_OPT' | When |
78/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT' | 'BSLS_ASSERT_OPT' |
79/// |'BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_OPT' | is active. |
80/// +---------------------------------------------------+-------------------+
81/// @endcode
82/// In build modes where any one of these macros is not active, the presence of
83/// the macros has no effect.
84///
85/// If any of these asserts are in effect and fail (because the reader-writer
86/// lock in question was unlocked), the behavior parallels the behavior of the
87/// assertion macros defined in `bsls_assert.h` -- `bsls::Assert::invokeHandler`
88/// is called, with a source code expression, the name of the source file, and
89/// the line number in the source file where the macro was called. If the
90/// default handler is installed, this will result in an error message and an
91/// abort.
92///
93/// ## Caveat: False Positives {#bslmt_readerwriterlockassert-caveat-false-positives}
94///
95///
96/// Preconditions on locks typically require that the lock exist *and* *is*
97/// *held* *by* *the* *calling* *thread*. Unfortunately, lock ownership is not
98/// recorded in the lock and cannot be confirmed. The absence of any lock when
99/// the calling thread should hold one is certainly a problem; however, the
100/// existence of a lock does not guarantee that the complete precondition is
101/// met.
102///
103/// ## Requirements on the Lock Type {#bslmt_readerwriterlockassert-requirements-on-the-lock-type}
104///
105///
106/// This system of macros accept pointers to reader-write lock objects that
107/// provide the methods:
108/// * `isLocked`,
109/// * `isLockedRead`, and
110/// * `isLockedWrite`
111///
112/// Two compatible classes are:
113/// * `bslmt::ReaderWriterLock` and
114/// * `bslmt::ReaderWriterMutex`
115///
116/// Although the required methods are typically `const`-qualified (i.e.,
117/// "accessor" methods), that is not a requriement. Some client lock classes
118/// may implement these methods in terms of `tryLock`/`unlock` methods that
119/// require non-`const` access to the lock.
120///
121/// ## Usage {#bslmt_readerwriterlockassert-usage}
122///
123///
124/// This section illustrates intended use of this component.
125///
126/// ### Example 1: Checking Consistency Within Private Methods {#bslmt_readerwriterlockassert-example-1-checking-consistency-within-private-methods}
127///
128///
129/// This example is an generalization of {@ref bslmt_mutexassert |Example 1:
130/// Checking Consistency Within a Private Method}. In that example, a mutex was
131/// used to control access. Here, the (simple) mutex is replaced with a
132/// `bslmt::ReaderWriterLock` that is allows multiple concurrent access to the
133/// queue when conditions allow.
134///
135/// Sometimes multithreaded code is written such that the author of a function
136/// requires that a caller has already acquired a lock. The
137/// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED*` family of assertions allows the
138/// programmers to detect, using defensive programming techniques, if the
139/// required lock has *not* been acquired.
140///
141/// Suppose we have a fully thread-safe queue that contains `int` values, and is
142/// guarded by an internal `bslmt::ReaderWriterLock` object.
143///
144/// First, we define the container class:
145/// @code
146/// /// This `class` provides a fully *thread-safe* unidirectional queue of
147/// /// `int` values. See {`bsls_glossary`|Fully Thread-Safe}. All public
148/// /// methods operate as single, atomic actions.
149/// class MyThreadSafeQueue {
150///
151/// // DATA
152/// bsl::deque<int> d_deque; // underlying non-*thread-safe*
153/// // standard container
154///
155/// mutable bslmt::ReaderWriterLock
156/// d_rwLock; // coordinate thread access
157///
158/// // PRIVATE MANIPULATOR
159///
160/// // Assign the value at the front of the queue to the specified
161/// // `*result`, and remove the value at the front of the queue;
162/// // return 0 if the queue was not initially empty, and a non-zero
163/// // value (with no effect) otherwise. The behavior is undefined
164/// // unless `d_rwLock` is locked for writing.
165/// int popImp(int *result);
166///
167/// // PRIVATE ACCESSOR
168///
169/// /// Return a `bsl::pair<int, int>` containing the number of elements
170/// /// and the mean value of the elements of this queue. The mean
171/// /// values is set to `DBL_MIN` if the number of elements is 0. The
172/// /// behavior is undefined unless the call has locked this queue
173/// /// (either a read lock or write lock).
174/// bsl::pair<int, double> getStats() const;
175///
176/// public:
177/// // ...
178///
179/// // MANIPULATORS
180///
181/// /// Assign the value at the front of the queue to the specified
182/// /// `*result`, and remove the value at the front of the queue;
183/// /// return 0 if the queue was not initially empty, and a non-zero
184/// /// value (with no effect) otherwise.
185/// int pop(int *result);
186///
187/// /// Assign the values of all the elements from this queue, in order,
188/// /// to the specified `*result`, and remove them from this queue.
189/// /// Any previous contents of `*result` are discarded. Note that, as
190/// /// with the other public manipulators, this entire operation occurs
191/// /// as a single, atomic action.
192/// void popAll(bsl::vector<int> *result);
193///
194/// /// Remove all elements from this queue if their mean exceeds the
195/// /// specified `limit`.
196/// void purgeAll(double limit);
197///
198/// /// Push the specified `value` onto this queue.
199/// void push(int value);
200///
201/// /// Push the values from the specified `first` (inclusive) to the
202/// /// specified `last` (exclusive) onto this queue.
203/// template <class INPUT_ITER>
204/// void pushRange(const INPUT_ITER& first, const INPUT_ITER& last);
205///
206/// // ACCESSORS
207///
208/// /// Return the mean value of the elements of this queue.
209/// double mean() const;
210///
211/// /// Return the number of elements in this queue.
212/// bsl::size_t numElements() const;
213/// };
214/// @endcode
215/// Notice that this version of the `MyThreadSafeQueue` class has two public
216/// accessors, `numElements` and `mean`, and an additional manipulator,
217/// `purgeAll`.
218///
219/// Then, we implement most of the manipulators:
220/// @code
221/// // PRIVATE MANIPULATOR
222/// int MyThreadSafeQueue::popImp(int *result)
223/// {
224/// BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE(&d_rwLock);
225///
226/// if (d_deque.empty()) {
227/// return -1; // RETURN
228/// }
229/// else {
230/// *result = d_deque.front();
231/// d_deque.pop_front();
232/// return 0; // RETURN
233/// }
234/// }
235///
236/// // MANIPULATORS
237/// int MyThreadSafeQueue::pop(int *result)
238/// {
239/// BSLS_ASSERT(result);
240///
241/// d_rwLock.lockWrite();
242/// int rc = popImp(result);
243/// d_rwLock.unlockWrite();
244/// return rc;
245/// }
246///
247/// void MyThreadSafeQueue::popAll(bsl::vector<int> *result)
248/// {
249/// BSLS_ASSERT(result);
250///
251/// const int size = static_cast<int>(d_deque.size());
252/// result->resize(size);
253/// int *begin = result->begin();
254/// for (int index = 0; index < size; ++index) {
255/// int rc = popImp(&begin[index]);
256/// BSLS_ASSERT(0 == rc);
257/// }
258/// }
259///
260/// void MyThreadSafeQueue::push(int value)
261/// {
262/// d_rwLock.lockWrite();
263/// d_deque.push_back(value);
264/// d_rwLock.unlockWrite();
265/// }
266///
267/// template <class INPUT_ITER>
268/// void MyThreadSafeQueue::pushRange(const INPUT_ITER& first,
269/// const INPUT_ITER& last)
270/// {
271/// d_rwLock.lockWrite();
272/// d_deque.insert(d_deque.begin(), first, last);
273/// d_rwLock.unlockWrite();
274/// }
275/// @endcode
276/// Notice that these implementations are identical to those shown in
277/// {@ref bslmt_mutexassert |Example 1} except that the `lock` calls to the
278/// `bslmt::Mutex` there have been changed here to `lockWrite` calls on a
279/// `bslmt::ReaderWriterLock`. Both operations provide exclusive access to the
280/// container.
281///
282/// Also notice that, having learned the lesson of {@ref bslmt_mutexassert |Example
283/// 1}, we were careful to acquire a write lock for the duration of each of
284/// these operation and to check the precondition of the private `popImp`
285/// method by using the `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE` macro.
286///
287/// Finally notice that we use the "normal" flavor of the macro (rather than the
288/// `*_SAFE` version) because this test is not particularly expensive.
289///
290/// Next, we implement the accessor methods of the container:
291/// @code
292/// // ACCESSORS
293/// double MyThreadSafeQueue::mean() const
294/// {
295/// d_rwLock.lockRead();
296/// bsl::pair<int, double> result = getStats();
297/// d_rwLock.unlockRead();
298/// return result.second;
299/// }
300///
301/// bsl::size_t MyThreadSafeQueue::numElements() const
302/// {
303/// d_rwLock.lockRead();
304/// bsl::size_t numElements = d_deque.size();
305/// d_rwLock.unlockRead();
306/// return numElements;
307/// }
308/// @endcode
309/// Notice that each of these methods acquire a read lock for the duration of
310/// the operation. These locks allow shared access provided that the container
311/// is not changed, a reasonable assumption for these `const`-qualified methods.
312///
313/// Also notice that the bulk of the work of `mean` is done by the private
314/// method `getStats`. One's might except the private method to confirm that a
315/// lock was acquired by using the
316/// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ` macro; however, the reason
317/// for creating that private method is so that it can be reused by the
318/// `purgeAll` method, a non-`const` method that requires a write lock. Thus,
319/// `getStats` is an occassion to use the
320/// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED` check (for either a read lock *or*
321/// a write lock).
322/// @code
323/// // PRIVATE ACCESSORS
324/// bsl::pair<int, double> MyThreadSafeQueue::getStats() const
325/// {
326/// BSLMT_READERWRITERLOCKASSERT_IS_LOCKED(&d_rwLock);
327///
328/// int numElements = d_deque.size();
329///
330/// if (0 == numElements) {
331/// return bsl::make_pair(numElements, DBL_MIN); // RETURN
332/// }
333///
334/// int sum = bsl::accumulate(d_deque.cbegin(), d_deque.cend(), 0);
335/// double mean = static_cast<double>(sum)
336/// / static_cast<double>(numElements);
337///
338/// return bsl::make_pair(numElements, mean);
339/// }
340/// @endcode
341/// Next, we implement the `purgeAll` method:
342/// @code
343/// void MyThreadSafeQueue::purgeAll(double limit)
344/// {
345/// d_rwLock.lockWrite();
346/// bsl::pair<int, double> results = getStats(); // requires some lock
347/// if (0 < results.first && limit < results.second) {
348/// for (int i = 0; i < results.first; ++i) {
349/// int dummy;
350/// int rc = popImp(&dummy); // requires a write lock
351/// assert(0 == rc);
352/// }
353/// }
354/// d_rwLock.unlockWrite();
355/// }
356/// @endcode
357/// Finally, we confirm that our accessors work as expected:
358/// @code
359/// /// Exercise the added methods of the `MyThreadSafeQueue` class.
360/// void testEnhancedThreadSafeQueue()
361/// {
362/// MyThreadSafeQueue queue;
363///
364/// const int rawData[] = { 17, 3, -20, 7, 28 };
365/// enum { k_RAW_DATA_LENGTH = sizeof rawData / sizeof *rawData };
366///
367/// queue.pushRange(rawData + 0, rawData + k_RAW_DATA_LENGTH);
368///
369/// assert(5 == queue.numElements());
370/// assert(7 == queue.mean());
371///
372/// queue.push(100000);
373/// queue.purgeAll(10);
374///
375/// assertV(queue.numElements(), 0 == queue.numElements());
376/// assertV(queue.mean() , DBL_MIN == queue.mean());
377/// }
378/// @endcode
379/// @}
380/** @} */
381/** @} */
382
383/** @addtogroup bsl
384 * @{
385 */
386/** @addtogroup bslmt
387 * @{
388 */
389/** @addtogroup bslmt_readerwriterlockassert
390 * @{
391 */
392
393#include <bslscm_version.h>
394
395#include <bsls_assert.h>
396
397#include <bsl_string.h> // 'std::strcmp'
398
399// ----------------------------------------------------------------------------
400
401#if defined(BSLS_ASSERT_IS_ACTIVE)
402 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED(rwLock_p) do { \
403 bslmt::ReaderWriterLockAssert_Imp::assertIsLocked( \
404 (rwLock_p), \
405 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED(" #rwLock_p ")", \
406 __FILE__, \
407 __LINE__, \
408 bsls::Assert::k_LEVEL_ASSERT); } while (false)
409#else
410 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED(rwLock_p) ((void) 0)
411#endif
412
413#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
414 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_SAFE(rwLock_p) do { \
415 bslmt::ReaderWriterLockAssert_Imp::assertIsLocked( \
416 (rwLock_p), \
417 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_SAFE(" #rwLock_p ")", \
418 __FILE__, \
419 __LINE__, \
420 bsls::Assert::k_LEVEL_SAFE); } while (false)
421#else
422 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_SAFE(rwLock_p) ((void) 0)
423#endif
424
425#if defined(BSLS_ASSERT_OPT_IS_ACTIVE)
426 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_OPT(rwLock_p) do { \
427 bslmt::ReaderWriterLockAssert_Imp::assertIsLocked( \
428 (rwLock_p), \
429 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_OPT(" #rwLock_p ")", \
430 __FILE__, \
431 __LINE__, \
432 bsls::Assert::k_LEVEL_OPT); } while (false)
433#else
434 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_OPT(rwLock_p) ((void) 0)
435#endif
436
437// ----------------------------------------------------------------------------
438
439#if defined(BSLS_ASSERT_IS_ACTIVE)
440 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ(rwLock_p) do { \
441 bslmt::ReaderWriterLockAssert_Imp::assertIsLockedRead( \
442 (rwLock_p), \
443 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ(" #rwLock_p ")", \
444 __FILE__, \
445 __LINE__, \
446 bsls::Assert::k_LEVEL_ASSERT); } while (false)
447#else
448 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ(rwLock_p) ((void) 0)
449#endif
450
451#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
452 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE(rwLock_p) do { \
453 bslmt::ReaderWriterLockAssert_Imp::assertIsLockedRead( \
454 (rwLock_p), \
455 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE(" #rwLock_p ")", \
456 __FILE__, \
457 __LINE__, \
458 bsls::Assert::k_LEVEL_SAFE); } while (false)
459#else
460 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE(rwLock_p) \
461 ((void) 0)
462#endif
463
464#if defined(BSLS_ASSERT_OPT_IS_ACTIVE)
465 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT(rwLock_p) do { \
466 bslmt::ReaderWriterLockAssert_Imp::assertIsLockedRead( \
467 (rwLock_p), \
468 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT(" #rwLock_p ")", \
469 __FILE__, \
470 __LINE__, \
471 bsls::Assert::k_LEVEL_OPT); } while (false)
472#else
473 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT(rwLock_p) \
474 ((void) 0)
475#endif
476
477// ----------------------------------------------------------------------------
478
479#if defined(BSLS_ASSERT_IS_ACTIVE)
480 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE(rwLock_p) do { \
481 bslmt::ReaderWriterLockAssert_Imp::assertIsLockedWrite( \
482 (rwLock_p), \
483 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE(" #rwLock_p ")", \
484 __FILE__, \
485 __LINE__, \
486 bsls::Assert::k_LEVEL_ASSERT); } while (false)
487#else
488 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE(rwLock_p) ((void) 0)
489#endif
490
491#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
492 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_SAFE(rwLock_p) do { \
493 bslmt::ReaderWriterLockAssert_Imp::assertIsLockedWrite( \
494 (rwLock_p), \
495 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_SAFE(" #rwLock_p ")", \
496 __FILE__, \
497 __LINE__, \
498 bsls::Assert::k_LEVEL_SAFE); } while (false)
499#else
500 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_SAFE(rwLock_p) \
501 ((void) 0)
502#endif
503
504#if defined(BSLS_ASSERT_OPT_IS_ACTIVE)
505 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_OPT(rwLock_p) do { \
506 bslmt::ReaderWriterLockAssert_Imp::assertIsLockedWrite( \
507 (rwLock_p), \
508 "BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_OPT(" #rwLock_p ")", \
509 __FILE__, \
510 __LINE__, \
511 bsls::Assert::k_LEVEL_OPT); } while (false)
512#else
513 #define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_OPT(rwLock_p) \
514 ((void) 0)
515#endif
516
517// ----------------------------------------------------------------------------
518
519
520namespace bslmt {
521
522 // ================================
523 // class ReaderWriterLockAssert_Imp
524 // ================================
525
526/// This `struct` provides a (component private) namespace for
527/// implementation functions of the assert macros defined in this component.
528/// This class should *not* be used directly in client code.
530
531 // CLASS METHODS
532
533 /// If the specified `rwLock` is not locked (i.e., neither a read lock
534 /// or a write lock), call `bsls::Assert::invokeHandler` with the
535 /// specified `text`, `file`, `line`, and `level`, where `text` is text
536 /// describing the assertion being performed, `file` is the name of the
537 /// source file that called the macro, `line` is the line number in the
538 /// file where the macro was called, and `level` is one of the
539 /// `bslsAssert::k_LEVEL_*` string literals. This function is intended
540 /// to implement `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED`,
541 /// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_SAFE`, and
542 /// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_OPT` and should not
543 /// otherwise be called directly.
544 template <class RW_LOCK>
545 static void assertIsLocked(RW_LOCK *rwLock,
546 const char *text,
547 const char *file,
548 int line,
549 const char *level);
550
551 /// If the specified `rwLock` is not locked for reading, call
552 /// `bsls::Assert::invokeHandler` with the specified `text`, `file`,
553 /// `line`, and `level`, where `text` is text describing the assertion
554 /// being performed, `file` is the name of the source file that called
555 /// the macro, `line` is the line number in the file where the macro was
556 /// called, and `level` is one of the `bslsAssert::k_LEVEL_*` string
557 /// literals. This function is intended to implement
558 /// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ`,
559 /// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE`, and
560 /// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT` and should not
561 /// otherwise be called directly.
562 template <class RW_LOCK>
563 static void assertIsLockedRead(RW_LOCK *rwLock,
564 const char *text,
565 const char *file,
566 int line,
567 const char *level);
568
569 /// If the specified `rwLock` is not locked for writing, call
570 /// `bsls::Assert::invokeHandler` with the specified `text`, `file`,
571 /// `line`, and `level`, where `text` is text describing the assertion
572 /// being performed, `file` is the name of the source file that called
573 /// the macro, `line` is the line number in the file where the macro was
574 /// called, and `level` is one of the `bsls::Assert::k_LEVEL_*` string
575 /// literals. This function is intended to implement
576 /// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ`,
577 /// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE`, and
578 /// `BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT` and should not
579 /// otherwise be called directly.
580 template <class RW_LOCK>
581 static void assertIsLockedWrite(RW_LOCK *rwLock,
582 const char *text,
583 const char *file,
584 int line,
585 const char *level);
586
587 /// Return `true` if the specified `level` compares equal to one of the
588 /// `bsls::Assert::k_LEVEL_*` string literals, and `false` otherwise.
589 static bool isValidLevel(const char *level);
590};
591
592// ============================================================================
593// INLINE DEFINITIONS
594// ============================================================================
595
596 // --------------------------------
597 // class ReaderWriterLockAssert_Imp
598 // --------------------------------
599
600
601// CLASS METHODS
602template <class RW_LOCK>
603inline
605 const char *text,
606 const char *file,
607 int line,
608 const char *level)
609{
610 BSLS_ASSERT(rwLock);
611 BSLS_ASSERT(text);
612 BSLS_ASSERT(file);
613 BSLS_ASSERT(level);
615
616 if (!rwLock->isLocked()) {
617 bsls::AssertViolation violation(text, file, line, level);
619 }
620}
621
622template <class RW_LOCK>
623inline
625 const char *text,
626 const char *file,
627 int line,
628 const char *level)
629{
630 BSLS_ASSERT(rwLock);
631 BSLS_ASSERT(text);
632 BSLS_ASSERT(file);
633 BSLS_ASSERT(level);
635
636 if (!rwLock->isLockedRead()) {
637 bsls::AssertViolation violation(text, file, line, level);
639 }
640}
641
642template <class RW_LOCK>
643inline
645 const char *text,
646 const char *file,
647 int line,
648 const char *level)
649{
650 BSLS_ASSERT(rwLock);
651 BSLS_ASSERT(text);
652 BSLS_ASSERT(file);
653 BSLS_ASSERT(level);
655
656 if (!rwLock->isLockedWrite()) {
657 bsls::AssertViolation violation(text, file, line, level);
659 }
660}
661
662inline
664{
665 BSLS_ASSERT(level);
666
667 return 0 == std::strcmp(level, bsls::Assert::k_LEVEL_SAFE)
668 || 0 == std::strcmp(level, bsls::Assert::k_LEVEL_OPT)
669 || 0 == std::strcmp(level, bsls::Assert::k_LEVEL_ASSERT)
670 || 0 == std::strcmp(level, bsls::Assert::k_LEVEL_INVOKE);
671
672}
673
674} // close package namespace
675
676
677#endif
678
679// ----------------------------------------------------------------------------
680// Copyright 2019 Bloomberg Finance L.P.
681//
682// Licensed under the Apache License, Version 2.0 (the "License");
683// you may not use this file except in compliance with the License.
684// You may obtain a copy of the License at
685//
686// http://www.apache.org/licenses/LICENSE-2.0
687//
688// Unless required by applicable law or agreed to in writing, software
689// distributed under the License is distributed on an "AS IS" BASIS,
690// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
691// See the License for the specific language governing permissions and
692// limitations under the License.
693// ----------------------------- END-OF-FILE ----------------------------------
694
695/** @} */
696/** @} */
697/** @} */
Definition bsls_assert.h:1929
static const char k_LEVEL_ASSERT[]
Definition bsls_assert.h:2046
static const char k_LEVEL_SAFE[]
Definition bsls_assert.h:2044
static BSLS_ASSERT_NORETURN_INVOKE_HANDLER void invokeHandler(const AssertViolation &violation)
static const char k_LEVEL_INVOKE[]
Definition bsls_assert.h:2047
static const char k_LEVEL_OPT[]
Definition bsls_assert.h:2045
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bslmt_barrier.h:344
Definition bslmt_readerwriterlockassert.h:529
static void assertIsLockedRead(RW_LOCK *rwLock, const char *text, const char *file, int line, const char *level)
Definition bslmt_readerwriterlockassert.h:624
static bool isValidLevel(const char *level)
Definition bslmt_readerwriterlockassert.h:663
static void assertIsLockedWrite(RW_LOCK *rwLock, const char *text, const char *file, int line, const char *level)
Definition bslmt_readerwriterlockassert.h:644
static void assertIsLocked(RW_LOCK *rwLock, const char *text, const char *file, int line, const char *level)
Definition bslmt_readerwriterlockassert.h:604