This class extends class ThreadLock, adding functionality to register 'acquirers' of type ThreadLock. Only with the second acquirer added, the lock is activated using method ThreadLock::SetSafeness . The goal is to not use a mutex, when such use is not needed. In occasions with very high frequency of acquisition, this can provide a performance benefit.
The following rules apply:
Using nulled acquirers:
Sometimes it is useful to add a nullptr
as an acquirer. A sample for this is found and explained static field StdOutputStreams. If the first acquirer is nullptr, the second should be added in a thread-safe way. This means, the code invoking AddAcquirer needs to care for itself, that this object is not acquired during this process. E.g. it can be done in the bootstrap section of a process, when no parallel threads were started. For further acquirers, such care does not need to be taken. While an acquirer must not be attached twice, 'anonymous' (nullptr) acquirers may. For each anonymous invocation of AddAcquirer, a corresponding call RemoveAcquirer is needed, to get back to Safeness::Unsafe.
Definition at line 48 of file smartlock.hpp.
#include <smartlock.hpp>
Public Static Field Index: | |
static ALIB_API SmartLock | StdOutputStreams |
Public Method Index: | |
SmartLock () | |
void | Acquire (const NCString &dbgFile, int dbgLine, const NCString &dbgFunc) |
ALIB_API int | AddAcquirer (ThreadLock *newAcquirer) |
ALIB_API int | CntAcquirers () |
ALIB_API void | Release () |
defined(ALIB_DOX) | |
ALIB_API int | RemoveAcquirer (ThreadLock *acquirer) |
Public Method Index: inherited from ThreadLock | |
ALIB_API | ThreadLock (lang::Safeness safeness=lang::Safeness::Safe) |
ALIB_API | ~ThreadLock () |
ALIB_API void | Acquire (const NCString &dbgFile, int dbgLine, const NCString &dbgFunc) |
int | CountAcquirements () const |
Thread * | GetOwner () const |
lang::Safeness | GetSafeness () const |
bool | IsOwnedByCurrentThread () const |
ALIB_API void | Release () |
defined(ALIB_DOX) | |
ALIB_API void | SetSafeness (lang::Safeness safeness) |
bool | WillRelease () const |
Additional Inherited Members | |
Public Field Index: inherited from ThreadLock | |
NCString | DbgOwnerFile =nullptr |
NCString | DbgOwnerFunc =nullptr |
int | DbgOwnerLine |
uint16_t | DbgRecursionWarningThreshold =10 |
integer | DbgWarningAfterWaitTimeInMillis =2000L |
|
protected |
The list of acquirers.
Definition at line 58 of file smartlock.hpp.
|
protected |
A lock for acquirer management.
Definition at line 55 of file smartlock.hpp.
|
static |
This is a static singleton of this class that allows to lock an application's standard output streams.
In multi-threaded processes, to protect the output streams from concurrent access, this smart lock might be used by any entity that writes data to the streams. Before it can be used (acquired and released), it is needed to register with the object using SmartLock::AddAcquirer . This has to be done once per thread that aims to write to the stream. Then, prior to writing, this object has to be acquired and after writing released.
Because often, the standard output stream and standard error stream are identical, ALib provides one single lock for both, to protect also against interwoven standard output and error information.
If the 'entity' that is registering is not of type ThreadLock it is allowed to provide nullptr
in the parameter of method AddAcquirer. In this case, the process of adding and removing acquirers is not performed in a thread safe way. Therefore it is advised to register so called anonymous (nullptr
) acquirers only at bootstrap time, when no parallel threads were started, yet.
If an application is deemed to always write to the standard output streams from within multiple threads, an alternative to registering each writing entity, is to invoke AddAcquirer just two times in a row with nullptr
at the start of a process and then never do this again (and never de-register). This way, no thread needs to register/de-register but threads may still Acquire and Release the lock without being registered. In other words, once a smart lock is enabled, subsequent registrations are just used to count and identify the de-registration.
Definition at line 174 of file smartlock.hpp.
|
inline |
Constructs a SmartLock. Parent ThreadLock is initialized to Unsafe mode.
Definition at line 68 of file smartlock.hpp.
Overwriting ThreadLock::Acquire. With debug builds, asserts that at least one acquirer is set.
sample.Acquire( ALIB_CALLER_PRUNED );
dbgFile | Caller information. Available only with debug builds. |
dbgLine | Caller information. Available only with debug builds. |
dbgFunc | Caller information. Available only with debug builds. |
Definition at line 87 of file smartlock.hpp.
int AddAcquirer | ( | ThreadLock * | newAcquirer | ) |
Adds an acquirer. With the second acquirer added, this lock will be set into safe mode.
newAcquirer | The acquirer to add. |
Definition at line 29 of file smartlock.cpp.
int CntAcquirers | ( | ) |
Returns the number of acquirers. This is for debug and statistics purposes.
Definition at line 23 of file smartlock.cpp.
void Release | ( | ) |
defined(ALIB_DOX)
Releases ownership of this object. If Acquire was called multiple times before, the same number of calls to this method have to be performed to release ownership.
Definition at line 163 of file threadlock.cpp.
int RemoveAcquirer | ( | ThreadLock * | acquirer | ) |
Removes an acquirer. If the amount of acquirers after removal equals 1
, then this lock will be set to unsafe mode.
acquirer | The acquirer to remove. |
Definition at line 92 of file smartlock.cpp.