pwxlib
0.8.9
Tools Library for C++ Development
|
Base class to make objects lockable via atomic_flag and lock counting. More...
#include <pwxCLockable.h>
Public Types | |
typedef std::mutex | lock_t |
Use standard mutex if no spinlocks are used. | |
Public Member Functions | |
CLockable () noexcept | |
Default ctor. | |
CLockable (const CLockable &src) noexcept | |
Copy ctor. More... | |
virtual | ~CLockable () noexcept |
~CLockable More... | |
bool | beThreadSafe () const noexcept |
true if thread safety is turned on More... | |
void | beThreadSafe (bool doLock) noexcept |
set thread safety to doLock More... | |
bool | clear_locks () noexcept |
remove all locks More... | |
bool | destroyed () const noexcept |
if true the object will no longer lock More... | |
void | do_locking (bool doLock) noexcept |
set thread safety to doLock More... | |
bool | is_locked () const noexcept |
return true if this object is locked More... | |
bool | is_locking () const noexcept |
true if thread safety is turned on More... | |
void | lock () noexcept |
lock this object More... | |
uint32_t | lock_count () const noexcept |
number of locks this thread holds on this object More... | |
bool | try_lock () noexcept |
try to lock and return at once More... | |
void | unlock () noexcept |
unlock this object More... | |
CLockable & | operator= (const CLockable &src) noexcept |
Assignment operator. More... | |
Protected Attributes | |
abool_t | isDestroyed = ATOMIC_VAR_INIT(false) |
Should be set to true by the destructors of deriving classes. | |
mord_t | memOrdLoad = PWX_MEMORDER_ACQUIRE |
to be used with atomic::load() | |
mord_t | memOrdStore = PWX_MEMORDER_RELEASE |
to be used with atomic::store() | |
Base class to make objects lockable via atomic_flag and lock counting.
Any class that is derived from this class gains the following methods:
If the owning thread destroys the CLockable instance, the destructor will unlock completely before going away. If another thread waits for a lock in the meantime, or if the destroying thread is not the lock owner, the behavior is undefined.
This class implements a recursive behavior. Every call to lock() by the current lock owner is counted. To unlock, the same amount of calls of the unlock() method is required.
However, there are two methods that might help out of tight spots, enabling otherwise impossible techniques: The method clear_locks() will completely unlock, no matter how often lock() was called. Further a thread can ask the object with lock_count() how many locks it currently holds.
Please keep in mind, however, that your design might be flawed if you find yourself in a situation in which you really need either method.
Enabling/Disabling locking : If you want to switch to a non-locking mode, this will require the switching thread to get a lock first. This way you will not leave your object in a state where turning locking back on suddenly leaves you with a lock from a long-gone thread.
Rule of thumb: Do only turn off locking directly after instanciating your object and before any other thread might have accessed it!
Important: It is strongly recommended that you use std::lock_guard or std::unique_lock to do the locking of any object derived from pwx::CLockable. You can use PWX_LOCK_GUARD(pointer) and PWX_DOUBLE_LOCK_GUARD(ptrA, ptrB) to do this rather simply. They are defined in pwx/general/pwx_macros.h.
atomic_flag spinlock versus mutex:
By default CLockable is compiled with PWX_USE_FLAGSPIN defined. This can be controlled by setting USE_SPINLOCK in the main Makefile to either YES or NO.
If you think using the full std::mutex for doing the locking then you can set this value to NO and compare the outcome of the speed tests of the testlib program.
|
noexcept |
Copy ctor.
All objects have their private locking. Only the state whether to actually do the locking is copied.
|
virtualnoexcept |
~CLockable
The default dtor will try to unlock a held mutex until it succeeds.
|
noexcept |
true if thread safety is turned on
return true if thread safety mode is turned on
Referenced by pwx::private_::CThreadElementStore::clear(), pwx::private_::CThreadElementStore::curr(), pwx::private_::CThreadElementStore::disable_thread_safety(), pwx::VTHashBase< key_t, data_t, THashElement< key_t, data_t > >::disable_thread_safety(), pwx::private_::CThreadElementStore::enable_thread_safety(), pwx::VTHashBase< key_t, data_t, THashElement< key_t, data_t > >::enable_thread_safety(), pwx::VTHashBase< key_t, data_t, THashElement< key_t, data_t > >::operator+=(), and pwx::VTHashBase< key_t, data_t, THashElement< key_t, data_t > >::operator=().
|
noexcept |
set thread safety to doLock
set thread safety mode to doLock This is just an alias for do_locking().
|
noexcept |
remove all locks
clear all locks from this thread.
If this thread is the current owner of the lock, and if there are locks in place, they are all cleared.
If this thread is not the owner, the method simply returns false.
References CURRENT_THREAD_ID.
|
noexcept |
if true the object will no longer lock
returns true if the data was destroyed
The destructor of TSingleElement and TDoubleElement will try to get a final lock on the element when it is destroyed. If another thread acquires a lock between the data destruction and this final dtor lock, destroyed() will return "true".
References isDestroyed, and memOrdLoad.
Referenced by pwx::TSingleElement< data_t >::insertBefore(), pwx::THashElement< size_t, curr_t >::insertNext(), pwx::TDoubleElement< data_t >::insertNext(), pwx::TSingleElement< data_t >::insertNext(), and pwx::TDoubleElement< data_t >::insertPrev().
|
noexcept |
set thread safety to doLock
switch whether to really use locking or not.
With this method you can switch the locking mechanics on/off for objects to be used in concurrency or strictly single threaded. The default is to turn locking on.
[in] | doLock | true to turn locking on, false to turn it off. |
References CURRENT_THREAD_ID.
Referenced by pwx::VElement::disable_thread_safety(), and pwx::VElement::enable_thread_safety().
|
noexcept |
return true if this object is locked
return true if this object is currently locked
References memOrdLoad.
|
noexcept |
true if thread safety is turned on
return true if the locking is turned on.
|
noexcept |
lock this object
lock
Lock this object for the current thread if locking is enabled.
References CURRENT_THREAD_ID, isDestroyed, and memOrdLoad.
Referenced by pwx::private_::CThreadElementStore::curr().
|
noexcept |
number of locks this thread holds on this object
return the number of locks on this object this thread has
References CURRENT_THREAD_ID.
Assignment operator.
All objects have their private locking. Only the state whether to actually do the locking is copied.
|
noexcept |
try to lock and return at once
try_lock
Try to lock this object.
References CURRENT_THREAD_ID, isDestroyed, and memOrdLoad.
Referenced by pwx::try_locks().
|
noexcept |
unlock this object
unlock
If locking is disabled or if the current thread does not hold the lock, nothing happens. Otherwise the last lock is released.
References CURRENT_THREAD_ID.
Referenced by pwx::private_::CThreadElementStore::curr(), pwx::try_locks(), and pwx::unlock_all().