43 # define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC) 45 # define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC) \ 46 AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC) 51 static bool singleton =
false;
53 ::Fatal(
"UniqueLockRecurseCount Ctor",
"Only one TReentrantRWLock using a UniqueLockRecurseCount is allowed.");
61 template <
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);
128 template <
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);
160 template <
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;
208 template <
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);
232 template <
typename MutexT,
typename RecurseCountsT>
234 size_t *fReadersCountLoc =
nullptr;
235 int fReadersCount = 0;
239 template <
typename MutexT,
typename RecurseCountsT>
241 size_t *fReadersCountLoc =
nullptr;
242 int fDeltaReadersCount = 0;
243 int fDeltaWriteRecurse = 0;
250 template <
typename MutexT,
typename RecurseCountsT>
251 std::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);
282 template <
typename MutexT,
typename RecurseCountsT>
283 std::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));
329 template <
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;
365 template <
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 ReadUnLock(TVirtualRWMutex::Hint_t *)
Release the lock in read mode.
Namespace for new ROOT classes and functions.
void Fatal(const char *location, const char *msgfmt,...)
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 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.
size_t fWriteRecurse
! Number of re-entry in the lock by the same thread.
void Apply(std::unique_ptr< StateDelta > &&delta)
Re-apply a delta.
#define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC)
State as returned by GetStateDelta() that can be passed to Restore()
TVirtualRWMutex::Hint_t * ReadLock()
Acquire the lock in read mode.
TVirtualRWMutex::Hint_t * WriteLock()
Acquire the lock in write mode.
Earlier lock state as returned by GetState() that can be passed to Restore()
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.