ECSTASY
All in the name
Loading...
Searching...
No Matches
ecstasy::thread::SharedRecursiveMutex Class Reference

Wrapper for std::shared_mutex allowing recursive locking by the same thread. More...

#include <SharedRecursiveMutex.hpp>

Collaboration diagram for ecstasy::thread::SharedRecursiveMutex:

Public Member Functions

 SharedRecursiveMutex ()=default
 Construct a new Shared Recursive Mutex.
 
 ~SharedRecursiveMutex ()=default
 Destroy the Shared Recursive Mutex.
 
void lock ()
 Lock the mutex with exclusive access.
 
void lock_shared () const
 Lock the mutex with shared access.
 
void lock () const
 Lock the mutex with shared access.
 
void unlock ()
 Unlock the mutex locked with exclusive access.
 
void unlock_shared () const
 Unlock the mutex locked with shared access.
 
void unlock () const
 Unlock the mutex locked with shared access.
 
constexpr const std::shared_mutexget_shared_mutex (void) noexcept
 Get the internal mutex.
 
constexpr int get_lock_count (void) const noexcept
 Get the number of recursive locks held by the current thread.
 
int get_shared_lock_count (void) const noexcept
 Get the number of recursive shared locks held by the current thread.
 
constexpr const std::atomic< std::thread::id > & get_owner (void) const noexcept
 Get the owner of the mutex.
 

Private Member Functions

bool has_shared_lock (void) const noexcept
 

Private Attributes

std::shared_mutex _shared_mutex
 Internal shared mutex.
 
std::atomic< std::thread::id_owner
 Owner of the mutex.
 
int _lock_count
 Lock count.
 
std::unordered_map< std::thread::id, int > _shared_locks
 Shared lock count.
 

Detailed Description

Wrapper for std::shared_mutex allowing recursive locking by the same thread.

Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Definition at line 28 of file SharedRecursiveMutex.hpp.

Constructor & Destructor Documentation

◆ SharedRecursiveMutex()

ecstasy::thread::SharedRecursiveMutex::SharedRecursiveMutex ( )
default

Construct a new Shared Recursive Mutex.

Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

◆ ~SharedRecursiveMutex()

ecstasy::thread::SharedRecursiveMutex::~SharedRecursiveMutex ( )
default

Destroy the Shared Recursive Mutex.

Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Member Function Documentation

◆ get_lock_count()

constexpr int ecstasy::thread::SharedRecursiveMutex::get_lock_count ( void  ) const
inlineconstexprnoexcept

Get the number of recursive locks held by the current thread.

Note
0 means the mutex is not locked by the current thread (or at least not in exclusive).
Warning
This value is not thread-safe and should only be used for debugging purposes.
Returns
constexpr int number of recursive locks held by the current thread.
Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Definition at line 132 of file SharedRecursiveMutex.hpp.

133 {
134 return _lock_count;
135 }

◆ get_owner()

constexpr const std::atomic< std::thread::id > & ecstasy::thread::SharedRecursiveMutex::get_owner ( void  ) const
inlineconstexprnoexcept

Get the owner of the mutex.

Note
If the mutex is not locked, the owner is std::thread::id().
This value is thread safe.
Returns
constexpr const std::atomic<std::thread::id>& owner of the mutex.
Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Definition at line 166 of file SharedRecursiveMutex.hpp.

167 {
168 return _owner;
169 }
std::atomic< std::thread::id > _owner
Owner of the mutex.

◆ get_shared_lock_count()

int ecstasy::thread::SharedRecursiveMutex::get_shared_lock_count ( void  ) const
noexcept

Get the number of recursive shared locks held by the current thread.

Note
0 means the mutex has no shared lock held by the current thread. The shared lock count is also incremented by 1 when the mutex is locked exclusively (only once) to keep track of the shared lock count before/within an exclusive lock to unset them during the exclusive lock and reset them after. Therefore the real count of shared locks is the return value minus 1 if the owner is not null (std::thread::id()).
Warning
This value is exposed for debugging purposes, you should not rely on it for your locks, use the lock/unlock methods instead.
Returns
constexpr int number of recursive shared locks held by the current thread.
Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-20)

Definition at line 82 of file SharedRecursiveMutex.cpp.

83 {
84 // Better than handling exceptions
85 if (has_shared_lock())
87 else
88 return 0;
89 }
T at(T... args)
std::unordered_map< std::thread::id, int > _shared_locks
Shared lock count.
T get_id(T... args)

◆ get_shared_mutex()

constexpr const std::shared_mutex & ecstasy::thread::SharedRecursiveMutex::get_shared_mutex ( void  )
inlineconstexprnoexcept

Get the internal mutex.

Returns
constexpr const std::shared_mutex & internal mutex.
Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Definition at line 116 of file SharedRecursiveMutex.hpp.

117 {
118 return _shared_mutex;
119 }
std::shared_mutex _shared_mutex
Internal shared mutex.

◆ has_shared_lock()

bool ecstasy::thread::SharedRecursiveMutex::has_shared_lock ( void  ) const
privatenoexcept

Definition at line 91 of file SharedRecursiveMutex.cpp.

92 {
96 }
T cend(T... args)
T find(T... args)

◆ lock() [1/2]

void ecstasy::thread::SharedRecursiveMutex::lock ( void  )

Lock the mutex with exclusive access.

Note
Waits until the mutex is available for exclusive access. (ie no shared or exclusive lock held by other threads)
If the lock is already acquired, only increment the lock count.
If the mutex has a shared lock held by the current thread, it will be upgraded to an exclusive lock and downgraded after unlock. For example : lock_shared(); lock(); unlock(); unlock_shared();
Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Definition at line 16 of file SharedRecursiveMutex.cpp.

17 {
19
20 if (_owner == this_id) {
21 // recursive locking
23 } else {
24 // Unlock the shared lock if any
25 if (get_shared_lock_count() > 0) {
27 // Add a count to avoid the unlock_shared() to be called before the unlock()
28 // While the thread has exclusive lock, there is no real shared_lock, therefore calling unlock_shared()
29 // would cause an error
30 ++_shared_locks[this_id];
31 }
32 // normal locking
34 _owner = this_id;
35 _lock_count = 1;
36 }
37 }
int get_shared_lock_count(void) const noexcept
Get the number of recursive shared locks held by the current thread.
T lock(T... args)
T unlock_shared(T... args)

◆ lock() [2/2]

void ecstasy::thread::SharedRecursiveMutex::lock ( ) const
inline

Lock the mutex with shared access.

Definition at line 75 of file SharedRecursiveMutex.hpp.

76 {
78 }
void lock_shared() const
Lock the mutex with shared access.

◆ lock_shared()

void ecstasy::thread::SharedRecursiveMutex::lock_shared ( void  ) const

Lock the mutex with shared access.

Note
If the shared lock is already acquired, only increment the lock count.
If the mutex has an exclusive lock held by the current thread, the shared lock request will be "stored" and applied after exclusive unlock if unlock_shared was not called before. For example: lock(); lock_shared(); unlock(); unlock_shared();
Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Definition at line 39 of file SharedRecursiveMutex.cpp.

40 {
42 // Increment the shared lock count for this thread
43 int &shared_lock_count = ++_shared_locks[this_id];
44
45 // If it is the first shared lock, the count is set to 1 by incrementing the 0 default initialized value
46 if (shared_lock_count == 1) {
47 if (_owner != this_id)
49 else
50 ++shared_lock_count;
51 }
52 }
T lock_shared(T... args)

◆ unlock() [1/2]

void ecstasy::thread::SharedRecursiveMutex::unlock ( void  )

Unlock the mutex locked with exclusive access.

Note
Decrement the lock count and unlock the mutex if the new lock count is 0.
If the mutex had shared locks held by the current thread before lock (and not unlocked until now), they will be re enabled.
Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Definition at line 54 of file SharedRecursiveMutex.cpp.

55 {
56 if (_lock_count > 1) {
57 // recursive unlocking
59 } else {
60 // normal unlocking
62 _lock_count = 0;
64 // Apply the remaining shared locks that were made before/inside the exclusive lock
65 if (get_shared_lock_count() > 0) {
66 // Remove the count added in lock() and call remaininc lock_shared()
69 }
70 }
71 }
T unlock(T... args)

◆ unlock() [2/2]

void ecstasy::thread::SharedRecursiveMutex::unlock ( ) const
inline

Unlock the mutex locked with shared access.

Definition at line 103 of file SharedRecursiveMutex.hpp.

104 {
106 }
void unlock_shared() const
Unlock the mutex locked with shared access.

◆ unlock_shared()

void ecstasy::thread::SharedRecursiveMutex::unlock_shared ( void  ) const

Unlock the mutex locked with shared access.

Note
Decrement the shared lock count and unlock the mutex if the new lock count is 0.
Author
Andréas Leroux (andre.nosp@m.as.l.nosp@m.eroux.nosp@m.@epi.nosp@m.tech..nosp@m.eu)
Since
1.0.0 (2024-04-02)

Definition at line 73 of file SharedRecursiveMutex.cpp.

74 {
75 int &_shared_lock_count = --_shared_locks.at(std::this_thread::get_id());
76
77 // If it was the last shared lock, unlock the shared mutex
78 if (_shared_lock_count == 0)
80 }

Member Data Documentation

◆ _lock_count

int ecstasy::thread::SharedRecursiveMutex::_lock_count
private

Lock count.

Definition at line 187 of file SharedRecursiveMutex.hpp.

◆ _owner

std::atomic<std::thread::id> ecstasy::thread::SharedRecursiveMutex::_owner
private

Owner of the mutex.

Definition at line 185 of file SharedRecursiveMutex.hpp.

◆ _shared_locks

std::unordered_map<std::thread::id, int> ecstasy::thread::SharedRecursiveMutex::_shared_locks
mutableprivate

Shared lock count.

Definition at line 189 of file SharedRecursiveMutex.hpp.

◆ _shared_mutex

std::shared_mutex ecstasy::thread::SharedRecursiveMutex::_shared_mutex
mutableprivate

Internal shared mutex.

Definition at line 183 of file SharedRecursiveMutex.hpp.


The documentation for this class was generated from the following files: