BDE 4.14.0 Production release
|
Macros | |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED(rwLock_p) ((void) 0) |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_SAFE(rwLock_p) ((void) 0) |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_OPT(rwLock_p) ((void) 0) |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ(rwLock_p) ((void) 0) |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE(rwLock_p) ((void) 0) |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT(rwLock_p) ((void) 0) |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE(rwLock_p) ((void) 0) |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_SAFE(rwLock_p) ((void) 0) |
#define | BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_OPT(rwLock_p) ((void) 0) |
Provide an assert macro for verifying reader-writer lock status.
This component provides macros for asserting that a reader-writer lock is locked. It does not distinguish between locks held by the current thread or other threads. If the macro is active in the current build mode, when the macro is called, if the supplied lock is unlocked, the assert handler installed for BSLS_ASSERT
will be called. The assert handler installed by default will report an error and abort the task. Note that the type of lock (pointer) passed to each of these macros is determined at compile-time. See {Requirements on the Lock Type} below.
The nine macros defined by the component are analogous to the macros defined by BSLS_ASSERT
:
In build modes where any one of these macros is not active, the presence of the macros has no effect.
If any of these asserts are in effect and fail (because the reader-writer lock in question was unlocked), the behavior parallels the behavior of the assertion macros defined in bsls_assert.h
– bsls::Assert::invokeHandler
is called, with a source code expression, the name of the source file, and the line number in the source file where the macro was called. If the default handler is installed, this will result in an error message and an abort.
Preconditions on locks typically require that the lock exist and is held by the calling thread. Unfortunately, lock ownership is not recorded in the lock and cannot be confirmed. The absence of any lock when the calling thread should hold one is certainly a problem; however, the existence of a lock does not guarantee that the complete precondition is met.
This system of macros accept pointers to reader-write lock objects that provide the methods:
isLocked
,isLockedRead
, andisLockedWrite
Two compatible classes are:
Although the required methods are typically const
-qualified (i.e., "accessor" methods), that is not a requriement. Some client lock classes may implement these methods in terms of tryLock
/unlock
methods that require non-const
access to the lock.
This section illustrates intended use of this component.
This example is an generalization of {bslmt_mutexassert |Example 1: Checking Consistency Within a Private Method}. In that example, a mutex was used to control access. Here, the (simple) mutex is replaced with a bslmt::ReaderWriterLock
that is allows multiple concurrent access to the queue when conditions allow.
Sometimes multithreaded code is written such that the author of a function requires that a caller has already acquired a lock. The BSLMT_READERWRITERLOCKASSERT_IS_LOCKED*
family of assertions allows the programmers to detect, using defensive programming techniques, if the required lock has not been acquired.
Suppose we have a fully thread-safe queue that contains int
values, and is guarded by an internal bslmt::ReaderWriterLock
object.
First, we define the container class:
Notice that this version of the MyThreadSafeQueue
class has two public accessors, numElements
and mean
, and an additional manipulator, purgeAll
.
Then, we implement most of the manipulators:
Notice that these implementations are identical to those shown in {bslmt_mutexassert |Example 1} except that the lock
calls to the bslmt::Mutex
there have been changed here to lockWrite
calls on a bslmt::ReaderWriterLock
. Both operations provide exclusive access to the container.
Also notice that, having learned the lesson of {bslmt_mutexassert |Example 1}, we were careful to acquire a write lock for the duration of each of these operation and to check the precondition of the private popImp
method by using the BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE
macro.
Finally notice that we use the "normal" flavor of the macro (rather than the *_SAFE
version) because this test is not particularly expensive.
Next, we implement the accessor methods of the container:
Notice that each of these methods acquire a read lock for the duration of the operation. These locks allow shared access provided that the container is not changed, a reasonable assumption for these const
-qualified methods.
Also notice that the bulk of the work of mean
is done by the private method getStats
. One's might except the private method to confirm that a lock was acquired by using the BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ
macro; however, the reason for creating that private method is so that it can be reused by the purgeAll
method, a non-const
method that requires a write lock. Thus, getStats
is an occassion to use the BSLMT_READERWRITERLOCKASSERT_IS_LOCKED
check (for either a read lock or a write lock).
Next, we implement the purgeAll
method:
Finally, we confirm that our accessors work as expected:
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED | ( | rwLock_p | ) | ((void) 0) |
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_OPT | ( | rwLock_p | ) | ((void) 0) |
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ | ( | rwLock_p | ) | ((void) 0) |
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_OPT | ( | rwLock_p | ) | ((void) 0) |
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_READ_SAFE | ( | rwLock_p | ) | ((void) 0) |
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_SAFE | ( | rwLock_p | ) | ((void) 0) |
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE | ( | rwLock_p | ) | ((void) 0) |
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_OPT | ( | rwLock_p | ) | ((void) 0) |
#define BSLMT_READERWRITERLOCKASSERT_IS_LOCKED_WRITE_SAFE | ( | rwLock_p | ) | ((void) 0) |