43# define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC)
45# define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC) \
46 AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC)
49Internal::UniqueLockRecurseCount::UniqueLockRecurseCount()
51 static bool singleton =
false;
53 ::Fatal(
"UniqueLockRecurseCount Ctor",
"Only one TReentrantRWLock using a UniqueLockRecurseCount is allowed.");
61template <
typename MutexT,
typename RecurseCountsT>
70 auto local = fRecurseCounts.GetLocal();
72 TVirtualRWMutex::Hint_t *hint =
nullptr;
79 hint = fRecurseCounts.IncrementReadCount(local, fMutex);
81 }
else if (fRecurseCounts.IsCurrentWriter(local)) {
88 hint = fRecurseCounts.IncrementReadCount(local, fMutex);
96 std::unique_lock<MutexT> lock(fMutex);
99 if (fWriter && fRecurseCounts.IsNotCurrentWriter(local)) {
100 auto readerCount = fRecurseCounts.GetLocalReadersCount(local);
101 if (readerCount == 0)
102 fCond.wait(lock, [
this] {
return !fWriter; });
115 hint = fRecurseCounts.IncrementReadCount(local);
128template <
typename MutexT,
typename RecurseCountsT>
131 size_t *localReaderCount;
134 auto local = fRecurseCounts.GetLocal();
135 std::lock_guard<MutexT> lock(fMutex);
136 localReaderCount = &(fRecurseCounts.GetLocalReadersCount(local));
138 localReaderCount =
reinterpret_cast<size_t*
>(hint);
142 if (fWriterReservation && fReaders == 0) {
144 std::lock_guard<MutexT> lock(fMutex);
146 --(*localReaderCount);
154 --(*localReaderCount);
160template <
typename MutexT,
typename RecurseCountsT>
163 ++fWriterReservation;
165 std::unique_lock<MutexT> lock(fMutex);
167 auto local = fRecurseCounts.GetLocal();
170 auto &readerCount = fRecurseCounts.GetLocalReadersCount(local);
171 TVirtualRWMutex::Hint_t *hint =
reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&readerCount);
173 fReaders -= readerCount;
176 if (fWriter && fRecurseCounts.IsNotCurrentWriter(local)) {
177 if (readerCount && fReaders == 0) {
182 fCond.wait(lock, [
this] {
return !fWriter; });
187 fRecurseCounts.SetIsWriter(local);
190 while (fReaderReservation) {
194 fCond.wait(lock, [
this] {
return fReaders == 0; });
197 fReaders += readerCount;
199 --fWriterReservation;
208template <
typename MutexT,
typename RecurseCountsT>
212 std::lock_guard<MutexT> lock(fMutex);
214 if (!fWriter || fRecurseCounts.fWriteRecurse == 0) {
215 Error(
"TReentrantRWLock::WriteUnLock",
"Write lock already released for %p",
this);
219 fRecurseCounts.DecrementWriteCount();
221 if (!fRecurseCounts.fWriteRecurse) {
224 auto local = fRecurseCounts.GetLocal();
225 fRecurseCounts.ResetIsWriter(local);
232template <
typename MutexT,
typename RecurseCountsT>
234 size_t *fReadersCountLoc =
nullptr;
235 int fReadersCount = 0;
236 size_t fWriteRecurse = 0;
239template <
typename MutexT,
typename RecurseCountsT>
241 size_t *fReadersCountLoc =
nullptr;
242 int fDeltaReadersCount = 0;
243 int fDeltaWriteRecurse = 0;
250template <
typename MutexT,
typename RecurseCountsT>
251std::unique_ptr<TVirtualRWMutex::State>
254 using State_t = TReentrantRWLockState<MutexT, RecurseCountsT>;
257 Error(
"TReentrantRWLock::GetStateBefore()",
"Must be write locked!");
261 auto local = fRecurseCounts.GetLocal();
262 if (fRecurseCounts.IsNotCurrentWriter(local)) {
263 Error(
"TReentrantRWLock::GetStateBefore()",
"Not holding the write lock!");
267 std::unique_ptr<State_t> pState(
new State_t);
269 std::lock_guard<MutexT> lock(fMutex);
270 pState->fReadersCountLoc = &(fRecurseCounts.GetLocalReadersCount(local));
272 pState->fReadersCount = *(pState->fReadersCountLoc);
275 pState->fWriteRecurse = fRecurseCounts.fWriteRecurse - 1;
281 return std::unique_ptr<BaseState_t>(pState.release());
290template <
typename MutexT,
typename RecurseCountsT>
291std::unique_ptr<TVirtualRWMutex::StateDelta>
293 using State_t = TReentrantRWLockState<MutexT, RecurseCountsT>;
294 using StateDelta_t = TReentrantRWLockStateDelta<MutexT, RecurseCountsT>;
295 auto& typedState =
static_cast<const State_t&
>(earlierState);
299 std::unique_ptr<StateDelta_t> pStateDelta(
new StateDelta_t);
300 pStateDelta->fReadersCountLoc = typedState.fReadersCountLoc;
301 pStateDelta->fDeltaReadersCount = *typedState.fReadersCountLoc - typedState.fReadersCount;
302 pStateDelta->fDeltaWriteRecurse = fRecurseCounts.fWriteRecurse - typedState.fWriteRecurse;
304 if (pStateDelta->fDeltaReadersCount < 0) {
305 Error(
"TReentrantRWLock::Rewind",
"Inconsistent read lock count!");
309 if (pStateDelta->fDeltaWriteRecurse < 0) {
310 Error(
"TReentrantRWLock::Rewind",
"Inconsistent write lock count!");
314 auto hint =
reinterpret_cast<TVirtualRWMutex::Hint_t *
>(typedState.fReadersCountLoc);
315 if (pStateDelta->fDeltaWriteRecurse != 0) {
317 fRecurseCounts.fWriteRecurse = typedState.fWriteRecurse + 1;
322 if (pStateDelta->fDeltaReadersCount != 0) {
324 *typedState.fReadersCountLoc = typedState.fReadersCount + 1;
325 fReaders = typedState.fReadersCount + 1;
331 return std::unique_ptr<TVirtualRWMutex::StateDelta>(std::move(pStateDelta));
337template <
typename MutexT,
typename RecurseCountsT>
340 Error(
"TReentrantRWLock::Apply",
"Cannot apply empty delta!");
344 using StateDelta_t = TReentrantRWLockStateDelta<MutexT, RecurseCountsT>;
345 const StateDelta_t* typedDelta =
static_cast<const StateDelta_t*
>(state.get());
347 if (typedDelta->fDeltaWriteRecurse < 0) {
348 Error(
"TReentrantRWLock::Apply",
"Negative write recurse count delta!");
351 if (typedDelta->fDeltaReadersCount < 0) {
352 Error(
"TReentrantRWLock::Apply",
"Negative read count delta!");
357 if (typedDelta->fDeltaWriteRecurse != 0) {
359 fRecurseCounts.fWriteRecurse += typedDelta->fDeltaWriteRecurse - 1;
361 if (typedDelta->fDeltaReadersCount != 0) {
364 fReaders += typedDelta->fDeltaReadersCount - 1;
365 *typedDelta->fReadersCountLoc += typedDelta->fDeltaReadersCount - 1;
373template <
typename MutexT,
typename RecurseCountsT>
376 auto local = fRecurseCounts.GetLocal();
377 size_t* localReadersCount;
379 std::lock_guard<MutexT> lock(fMutex);
380 localReadersCount = &(fRecurseCounts.GetLocalReadersCount(local));
382 if (localReadersCount != presumedLocalReadersCount) {
383 Error(
"TReentrantRWLock::AssertReadCountLocIsFromCurrentThread",
"ReadersCount is from different thread!");
void Error(const char *location, const char *msgfmt,...)
void Fatal(const char *location, const char *msgfmt,...)
#define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC)
void WriteUnLock(TVirtualRWMutex::Hint_t *)
Release the lock in write mode.
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.
TVirtualRWMutex::Hint_t * WriteLock()
Acquire the lock in write mode.
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.
std::unique_ptr< State > GetStateBefore()
Get the lock state before the most recent write lock was taken.
void Apply(std::unique_ptr< StateDelta > &&delta)
Re-apply a delta.
Namespace for new ROOT classes and functions.
State as returned by GetStateDelta() that can be passed to Restore()
Earlier lock state as returned by GetState() that can be passed to Restore()