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.
State as returned by GetStateDelta() that can be passed to Restore()
Earlier lock state as returned by GetState() that can be passed to Restore()