13#ifndef ROOT_TReentrantRWLock
14#define ROOT_TReentrantRWLock
21#include <condition_variable>
23#include <unordered_map>
26#include "tbb/enumerable_thread_specific.h"
32 using Hint_t = TVirtualRWMutex::Hint_t;
51 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->
fReadersCount));
54 template <
typename MutexT>
61 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->
fReadersCount));
64 template <
typename MutexT>
93 using Hint_t = TVirtualRWMutex::Hint_t;
107 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&count);
110 template <
typename MutexT>
113 std::unique_lock<MutexT> lock(mutex);
120 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&count);
123 template <
typename MutexT>
126 std::unique_lock<MutexT> lock(mutex);
156struct RecurseCountsTBB {
157 using Hint_t = TVirtualRWMutex::Hint_t;
160 size_t fReadersCount = 0;
161 bool fIsWriter =
false;
163 tbb::enumerable_thread_specific<LocalCounts> fLocalCounts;
164 size_t fWriteRecurse = 0;
166 using local_t = LocalCounts *;
168 local_t GetLocal() {
return &fLocalCounts.local(); }
170 Hint_t *IncrementReadCount(local_t &local)
172 ++(local->fReadersCount);
173 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
176 template <
typename MutexT>
177 Hint_t *IncrementReadCount(local_t &local,
MutexT &)
179 return IncrementReadCount(local);
182 Hint_t *DecrementReadCount(local_t &local)
184 --(local->fReadersCount);
185 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
188 template <
typename MutexT>
189 Hint_t *DecrementReadCount(local_t &local,
MutexT &)
191 return DecrementReadCount(local);
194 void ResetReadCount(local_t &local,
int newvalue) { local->fReadersCount = newvalue; }
196 bool IsCurrentWriter(local_t &local) {
return local->fIsWriter; }
197 bool IsNotCurrentWriter(local_t &local) {
return !local->fIsWriter; }
199 void SetIsWriter(local_t &local)
205 local->fIsWriter =
true;
208 void DecrementWriteCount() { --fWriteRecurse; }
210 void ResetIsWriter(local_t &local) { local->fIsWriter =
false; }
212 size_t &GetLocalReadersCount(local_t &local) {
return local->fReadersCount; }
215struct RecurseCountsTBBUnique {
216 using Hint_t = TVirtualRWMutex::Hint_t;
219 size_t fReadersCount = 0;
220 bool fIsWriter =
false;
222 tbb::enumerable_thread_specific<LocalCounts, tbb::cache_aligned_allocator<LocalCounts>, tbb::ets_key_per_instance>
224 size_t fWriteRecurse = 0;
226 using local_t = LocalCounts *;
228 local_t GetLocal() {
return &fLocalCounts.local(); }
230 Hint_t *IncrementReadCount(local_t &local)
232 ++(local->fReadersCount);
233 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
236 template <
typename MutexT>
237 Hint_t *IncrementReadCount(local_t &local,
MutexT &)
239 return IncrementReadCount(local);
242 Hint_t *DecrementReadCount(local_t &local)
244 --(local->fReadersCount);
245 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
248 template <
typename MutexT>
249 Hint_t *DecrementReadCount(local_t &local,
MutexT &)
251 return DecrementReadCount(local);
254 void ResetReadCount(local_t &local,
int newvalue) { local->fReadersCount = newvalue; }
256 bool IsCurrentWriter(local_t &local) {
return local->fIsWriter; }
257 bool IsNotCurrentWriter(local_t &local) {
return !local->fIsWriter; }
259 void SetIsWriter(local_t &local)
265 local->fIsWriter =
true;
268 void DecrementWriteCount() { --fWriteRecurse; }
270 void ResetIsWriter(local_t &local) { local->fIsWriter =
false; }
272 size_t &GetLocalReadersCount(local_t &local) {
return local->fReadersCount; }
278template <
typename MutexT = ROOT::TSpinMutex,
typename RecurseCountsT = Internal::RecurseCounts>
306 TVirtualRWMutex::Hint_t *
ReadLock();
312 std::unique_ptr<StateDelta>
Rewind(
const State &earlierState);
313 void Apply(std::unique_ptr<StateDelta> &&delta);
std::condition_variable_any fCond
! RWlock internal condition variable
void WriteUnLock(TVirtualRWMutex::Hint_t *)
Release the lock in write mode.
TVirtualRWMutex::State State
std::atomic< int > fReaderReservation
! A reader wants access
std::unique_ptr< StateDelta > Rewind(const State &earlierState)
Rewind to an earlier mutex state, returning the delta.
TVirtualRWMutex::Hint_t * ReadLock()
Acquire the lock in read mode.
RecurseCountsT fRecurseCounts
! Trackers for re-entry in the lock by the same thread.
TVirtualRWMutex::Hint_t * WriteLock()
Acquire the lock in write mode.
std::atomic< bool > fWriter
! Is there a writer?
std::atomic< int > fReaders
! Number of readers
void ReadUnLock(TVirtualRWMutex::Hint_t *)
Release the lock in read mode.
void AssertReadCountLocIsFromCurrentThread(const size_t *presumedLocalReadersCount)
Assert that presumedLocalReadersCount really matches the local read count.
MutexT fMutex
! RWlock internal mutex
std::unique_ptr< State > GetStateBefore()
Get the lock state before the most recent write lock was taken.
TReentrantRWLock()
Regular constructor.
void Apply(std::unique_ptr< StateDelta > &&delta)
Re-apply a delta.
std::atomic< int > fWriterReservation
! A writer wants access
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Hint_t * DecrementReadCount(local_t &local)
size_t fWriteRecurse
! Number of re-entry in the lock by the same thread.
Hint_t * DecrementReadCount(local_t &local, MutexT &mutex)
bool IsNotCurrentWriter(local_t &local) const
std::unordered_map< std::thread::id, size_t > ReaderColl_t
bool IsCurrentWriter(local_t &local) const
void ResetIsWriter(local_t &)
std::thread::id fWriterThread
! Holder of the write lock
void DecrementWriteCount()
TVirtualRWMutex::Hint_t Hint_t
Hint_t * IncrementReadCount(local_t &local)
void ResetReadCount(local_t &local, int newvalue)
ReaderColl_t fReadersCount
! Set of reader thread ids
Hint_t * IncrementReadCount(local_t &local, MutexT &mutex)
size_t & GetLocalReadersCount(local_t &local)
void SetIsWriter(local_t &local)
bool IsCurrentWriter(local_t &local)
Hint_t * DecrementReadCount(local_t &local)
bool IsNotCurrentWriter(local_t &local)
Hint_t * IncrementReadCount(local_t &local, MutexT &)
void ResetReadCount(local_t &local, int newvalue)
TVirtualRWMutex::Hint_t Hint_t
void DecrementWriteCount()
void ResetIsWriter(local_t &local)
Hint_t * IncrementReadCount(local_t &local)
Hint_t * DecrementReadCount(local_t &local, MutexT &)
size_t & GetLocalReadersCount(local_t &local)
void SetIsWriter(local_t &local)
size_t fWriteRecurse
! Number of re-entry in the lock by the same thread.
State as returned by GetStateDelta() that can be passed to Restore()
Earlier lock state as returned by GetState() that can be passed to Restore()