13 #ifndef ROOT_TReentrantRWLock
14 #define ROOT_TReentrantRWLock
21 #include <condition_variable>
23 #include <unordered_map>
27 struct UniqueLockRecurseCount {
28 using Hint_t = TVirtualRWMutex::Hint_t;
31 size_t fReadersCount = 0;
32 bool fIsWriter =
false;
34 size_t fWriteRecurse = 0;
36 UniqueLockRecurseCount();
38 using local_t = LocalCounts*;
41 TTHREAD_TLS_DECL(LocalCounts, gLocal);
45 Hint_t *IncrementReadCount(local_t &local) {
46 ++(local->fReadersCount);
47 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
50 template <
typename MutexT>
51 Hint_t *IncrementReadCount(local_t &local, MutexT &) {
52 return IncrementReadCount(local);
55 Hint_t *DecrementReadCount(local_t &local) {
56 --(local->fReadersCount);
57 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
60 template <
typename MutexT>
61 Hint_t *DecrementReadCount(local_t &local, MutexT &) {
62 return DecrementReadCount(local);
65 void ResetReadCount(local_t &local,
int newvalue) {
66 local->fReadersCount = newvalue;
69 bool IsCurrentWriter(local_t &local) {
return local->fIsWriter; }
70 bool IsNotCurrentWriter(local_t &local) {
return !local->fIsWriter; }
72 void SetIsWriter(local_t &local)
78 local->fIsWriter =
true;
81 void DecrementWriteCount() { --fWriteRecurse; }
83 void ResetIsWriter(local_t &local) { local->fIsWriter =
false; }
85 size_t &GetLocalReadersCount(local_t &local) {
return local->fReadersCount; }
88 struct RecurseCounts {
89 using Hint_t = TVirtualRWMutex::Hint_t;
90 using ReaderColl_t = std::unordered_map<std::thread::id, size_t>;
93 std::thread::id fWriterThread;
94 ReaderColl_t fReadersCount;
96 using local_t = std::thread::id;
98 local_t GetLocal()
const {
return std::this_thread::get_id(); }
100 Hint_t *IncrementReadCount(local_t &local) {
101 auto &count = fReadersCount[local];
103 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&count);
106 template <
typename MutexT>
107 Hint_t *IncrementReadCount(local_t &local, MutexT &mutex)
109 std::unique_lock<MutexT> lock(mutex);
110 return IncrementReadCount(local);
113 Hint_t *DecrementReadCount(local_t &local) {
114 auto &count = fReadersCount[local];
116 return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&count);
119 template <
typename MutexT>
120 Hint_t *DecrementReadCount(local_t &local, MutexT &mutex)
122 std::unique_lock<MutexT> lock(mutex);
123 return DecrementReadCount(local);
126 void ResetReadCount(local_t &local,
int newvalue) {
127 fReadersCount[local] = newvalue;
130 bool IsCurrentWriter(local_t &local)
const {
return fWriterThread == local; }
131 bool IsNotCurrentWriter(local_t &local)
const {
return fWriterThread != local; }
133 void SetIsWriter(local_t &local)
139 fWriterThread = local;
142 void DecrementWriteCount() { --fWriteRecurse; }
144 void ResetIsWriter(local_t & ) { fWriterThread = std::thread::id(); }
146 size_t &GetLocalReadersCount(local_t &local) {
return fReadersCount[local]; }
152 template <
typename MutexT = ROOT::TSpinMutex,
typename RecurseCountsT = Internal::RecurseCounts>
153 class TReentrantRWLock {
156 std::atomic<int> fReaders;
157 std::atomic<int> fReaderReservation;
158 std::atomic<int> fWriterReservation;
159 std::atomic<bool> fWriter;
161 std::condition_variable_any fCond;
163 RecurseCountsT fRecurseCounts;
170 void AssertReadCountLocIsFromCurrentThread(
const size_t* presumedLocalReadersCount);
173 using State = TVirtualRWMutex::State;
174 using StateDelta = TVirtualRWMutex::StateDelta;
178 TReentrantRWLock() : fReaders(0), fReaderReservation(0), fWriterReservation(0), fWriter(false) {}
180 TVirtualRWMutex::Hint_t *ReadLock();
181 void ReadUnLock(TVirtualRWMutex::Hint_t *);
182 TVirtualRWMutex::Hint_t *WriteLock();
183 void WriteUnLock(TVirtualRWMutex::Hint_t *);
185 std::unique_ptr<State> GetStateBefore();
186 std::unique_ptr<StateDelta> Rewind(
const State &earlierState);
187 void Apply(std::unique_ptr<StateDelta> &&delta);