Provide a multi-reader/single-writer lock.
More...
Namespaces |
namespace | bslmt |
Detailed Description
- Outline
-
-
- Purpose:
- Provide a multi-reader/single-writer lock.
-
- Classes:
-
- See also:
- Component bslmt_readerwriterlock, Component bslmt_readlockguard, Component bslmt_writelockguard, Component bslmt_readerwriterlockassert
-
- Description:
- This component defines an efficient multi-reader/single-writer lock mechanism,
bslmt::ReaderWriterMutex
. It is designed to allow concurrent read access to a shared resource while still controlling write access.
- Reader-writer locks are generally used for resources that are frequently read and less frequently updated. Unlike other lock mechanisms (e.g., "mutexes"), reader-writer locks provide two distinct but mutually exclusive lock states: a read lock state, and a write lock state.
- To the extent the implementation's underlying mutex prevents a thread from starving, readers can not be starved by writers and writers can not be starved by readers. If the underlying mutex, to some extent, favors re-acquisition of the mutex to allowing a new thread to obtain the mutex (e.g., the mutex obtained on Linux), this reader-writer lock is writer biased since writers can re-acquire the lock in the presence of readers but readers will not be able to re-acquire the lock in the presence of writers.
-
- bslmt Read/Write Locking Components:
-
bslmt::ReaderWriterMutex
(defined in this component). Preferred for most use-cases, has been shown to be faster than bslmt::ReaderWriterLock
under most conditions and is generally the best choice.
-
bslmt::ReaderWriterLock
: Preferred only when very long hold times are anticipated. It also provides upgrade*
methods from a locked-for-read state to a locked-for-write state, but the use of this feature is discouraged as it has performed poorly on benchmarks.
-
bslmt::RWMutex
: Deprecated.
- Note that for extremely short hold times and very high concurrency, a
bslmt::Mutex
might outperform all of the above.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Maintaining an Account Balance:
- The following snippets of code illustrate the use of
bslmt::ReaderWriterMutex
to write a thread-safe class, my_Account
. Note the typical use of mutable
for the lock: class my_Account {
bsls::Types::Uint64 d_pennies;
mutable bslmt::ReaderWriterMutex d_lock;
public:
my_Account();
my_Account(const my_Account& original);
~my_Account();
my_Account& operator=(const my_Account& rhs);
void deposit(bsls::Types::Uint64 pennies);
int withdraw(bsls::Types::Uint64 pennies);
bsls::Types::Uint64 balanceInPennies() const;
};
my_Account::my_Account()
: d_pennies(0)
{
}
my_Account::my_Account(const my_Account& original)
: d_pennies(original.balanceInPennies())
{
}
my_Account::~my_Account()
{
}
my_Account& my_Account::operator=(const my_Account& rhs)
{
Where appropriate, clients should use a lock-guard to ensure that an acquired mutex is always properly released, even if an exception is thrown. d_lock.lockWrite();
d_pennies = rhs.balanceInPennies();
d_lock.unlockWrite();
return *this;
}
void my_Account::deposit(bsls::Types::Uint64 pennies)
{
d_lock.lockWrite();
d_pennies += pennies;
d_lock.unlockWrite();
}
int my_Account::withdraw(bsls::Types::Uint64 pennies)
{
int rv = 0;
d_lock.lockWrite();
if (pennies <= d_pennies) {
d_pennies -= pennies;
}
else {
rv = 1;
}
d_lock.unlockWrite();
return rv;
}
bsls::Types::Uint64 my_Account::balanceInPennies() const
{
d_lock.lockRead();
bsls::Types::Uint64 rv = d_pennies;
d_lock.unlockRead();
return rv;
}
The atomic my_Account
methods are used as expected: my_Account account;
account.deposit(10050);
assert(10050 == account.balanceInPennies());
bsls::Types::Uint64 paycheckInPennies = 5025;
account.deposit(paycheckInPennies);
assert(15075 == account.balanceInPennies());