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*;
169 return &fLocalCounts.local();
172 Hint_t *IncrementReadCount(local_t &local) {
173 ++(local->fReadersCount);
174 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
177 template <
typename MutexT>
178 Hint_t *IncrementReadCount(local_t &local,
MutexT &) {
179 return IncrementReadCount(local);
182 Hint_t *DecrementReadCount(local_t &local) {
183 --(local->fReadersCount);
184 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
187 template <
typename MutexT>
188 Hint_t *DecrementReadCount(local_t &local,
MutexT &) {
189 return DecrementReadCount(local);
192 void ResetReadCount(local_t &local,
int newvalue) {
193 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> fLocalCounts;
223 size_t fWriteRecurse = 0;
225 using local_t = LocalCounts*;
228 return &fLocalCounts.local();
231 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 &) {
238 return IncrementReadCount(local);
241 Hint_t *DecrementReadCount(local_t &local) {
242 --(local->fReadersCount);
243 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
246 template <
typename MutexT>
247 Hint_t *DecrementReadCount(local_t &local,
MutexT &) {
248 return DecrementReadCount(local);
251 void ResetReadCount(local_t &local,
int newvalue) {
252 local->fReadersCount = newvalue;
255 bool IsCurrentWriter(local_t &local) {
return local->fIsWriter; }
256 bool IsNotCurrentWriter(local_t &local) {
return !local->fIsWriter; }
258 void SetIsWriter(local_t &local)
264 local->fIsWriter =
true;
267 void DecrementWriteCount() { --fWriteRecurse; }
269 void ResetIsWriter(local_t &local) { local->fIsWriter =
false; }
271 size_t &GetLocalReadersCount(local_t &local) {
return local->fReadersCount; }
277template <
typename MutexT = ROOT::TSpinMutex,
typename RecurseCountsT = Internal::RecurseCounts>
305 TVirtualRWMutex::Hint_t *
ReadLock();
311 std::unique_ptr<StateDelta>
Rewind(
const State &earlierState);
312 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()