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>;
256 Error(
"TReentrantRWLock::GetStateBefore()",
"Must be write locked!");
260 auto local = fRecurseCounts.GetLocal();
261 if (fRecurseCounts.IsNotCurrentWriter(local)) {
262 Error(
"TReentrantRWLock::GetStateBefore()",
"Not holding the write lock!");
266 std::unique_ptr<State_t> pState(
new State_t);
268 std::lock_guard<MutexT> lock(fMutex);
269 pState->fReadersCountLoc = &(fRecurseCounts.GetLocalReadersCount(local));
271 pState->fReadersCount = *(pState->fReadersCountLoc);
274 pState->fWriteRecurse = fRecurseCounts.fWriteRecurse - 1;
276 return std::move(pState);
282template <
typename MutexT,
typename RecurseCountsT>
283std::unique_ptr<TVirtualRWMutex::StateDelta>
285 using State_t = TReentrantRWLockState<MutexT, RecurseCountsT>;
286 using StateDelta_t = TReentrantRWLockStateDelta<MutexT, RecurseCountsT>;
287 auto& typedState =
static_cast<const State_t&
>(earlierState);
291 std::unique_ptr<StateDelta_t> pStateDelta(
new StateDelta_t);
292 pStateDelta->fReadersCountLoc = typedState.fReadersCountLoc;
293 pStateDelta->fDeltaReadersCount = *typedState.fReadersCountLoc - typedState.fReadersCount;
294 pStateDelta->fDeltaWriteRecurse = fRecurseCounts.fWriteRecurse - typedState.fWriteRecurse;
296 if (pStateDelta->fDeltaReadersCount < 0) {
297 Error(
"TReentrantRWLock::Rewind",
"Inconsistent read lock count!");
301 if (pStateDelta->fDeltaWriteRecurse < 0) {
302 Error(
"TReentrantRWLock::Rewind",
"Inconsistent write lock count!");
306 auto hint =
reinterpret_cast<TVirtualRWMutex::Hint_t *
>(typedState.fReadersCountLoc);
307 if (pStateDelta->fDeltaWriteRecurse != 0) {
309 fRecurseCounts.fWriteRecurse = typedState.fWriteRecurse + 1;
314 if (pStateDelta->fDeltaReadersCount != 0) {
316 *typedState.fReadersCountLoc = typedState.fReadersCount + 1;
317 fReaders = typedState.fReadersCount + 1;
323 return std::unique_ptr<TVirtualRWMutex::StateDelta>(std::move(pStateDelta));
329template <
typename MutexT,
typename RecurseCountsT>
332 Error(
"TReentrantRWLock::Apply",
"Cannot apply empty delta!");
336 using StateDelta_t = TReentrantRWLockStateDelta<MutexT, RecurseCountsT>;
337 const StateDelta_t* typedDelta =
static_cast<const StateDelta_t*
>(state.get());
339 if (typedDelta->fDeltaWriteRecurse < 0) {
340 Error(
"TReentrantRWLock::Apply",
"Negative write recurse count delta!");
343 if (typedDelta->fDeltaReadersCount < 0) {
344 Error(
"TReentrantRWLock::Apply",
"Negative read count delta!");
349 if (typedDelta->fDeltaWriteRecurse != 0) {
351 fRecurseCounts.fWriteRecurse += typedDelta->fDeltaWriteRecurse - 1;
353 if (typedDelta->fDeltaReadersCount != 0) {
356 fReaders += typedDelta->fDeltaReadersCount - 1;
357 *typedDelta->fReadersCountLoc += typedDelta->fDeltaReadersCount - 1;
365template <
typename MutexT,
typename RecurseCountsT>
368 auto local = fRecurseCounts.GetLocal();
369 size_t* localReadersCount;
371 std::lock_guard<MutexT> lock(fMutex);
372 localReadersCount = &(fRecurseCounts.GetLocalReadersCount(local));
374 if (localReadersCount != presumedLocalReadersCount) {
375 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()