43# define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC)
44# define R__MAYBE_ASSERT_WITH_LOCAL_LOCK(where,msg,what)
46# define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC) \
47 AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC)
48#define R__MAYBE_ASSERT_WITH_LOCAL_LOCK(where, msg, what) \
50 std::unique_lock<MutexT> lock(fMutex); \
51 auto local = fRecurseCounts.GetLocal(); \
53 Error(where, "%s", msg); \
59 static bool singleton =
false;
61 ::Fatal(
"UniqueLockRecurseCount Ctor",
"Only one TReentrantRWLock using a UniqueLockRecurseCount is allowed.");
69template <
typename MutexT,
typename RecurseCountsT>
80 TVirtualRWMutex::Hint_t *hint =
nullptr;
104 std::unique_lock<MutexT> lock(
fMutex);
109 if (readerCount == 0)
136template <
typename MutexT,
typename RecurseCountsT>
139 size_t *localReaderCount;
143 std::lock_guard<MutexT> lock(
fMutex);
146 localReaderCount =
reinterpret_cast<size_t*
>(hint);
152 std::lock_guard<MutexT> lock(
fMutex);
154 --(*localReaderCount);
162 --(*localReaderCount);
168template <
typename MutexT,
typename RecurseCountsT>
173 std::unique_lock<MutexT> lock(
fMutex);
179 TVirtualRWMutex::Hint_t *hint =
reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&readerCount);
216template <
typename MutexT,
typename RecurseCountsT>
220 std::lock_guard<MutexT> lock(
fMutex);
223 Error(
"TReentrantRWLock::WriteUnLock",
"Write lock already released for %p",
this);
240template <
typename MutexT,
typename RecurseCountsT>
242 size_t *fReadersCountLoc =
nullptr;
243 int fReadersCount = 0;
244 size_t fWriteRecurse = 0;
247template <
typename MutexT,
typename RecurseCountsT>
249 size_t *fReadersCountLoc =
nullptr;
250 int fDeltaReadersCount = 0;
251 int fDeltaWriteRecurse = 0;
258template <
typename MutexT,
typename RecurseCountsT>
259std::unique_ptr<TVirtualRWMutex::State>
262 using State_t = TReentrantRWLockState<MutexT, RecurseCountsT>;
265 Error(
"TReentrantRWLock::GetStateBefore()",
"Must be write locked!");
271 Error(
"TReentrantRWLock::GetStateBefore()",
"Not holding the write lock!");
275 std::unique_ptr<State_t> pState(
new State_t);
277 std::lock_guard<MutexT> lock(
fMutex);
278 pState->fReadersCountLoc = &(
fRecurseCounts.GetLocalReadersCount(local));
280 pState->fReadersCount = *(pState->fReadersCountLoc);
289 return std::unique_ptr<BaseState_t>(pState.release());
298template <
typename MutexT,
typename RecurseCountsT>
299std::unique_ptr<TVirtualRWMutex::StateDelta>
301 using State_t = TReentrantRWLockState<MutexT, RecurseCountsT>;
302 using StateDelta_t = TReentrantRWLockStateDelta<MutexT, RecurseCountsT>;
303 auto& typedState =
static_cast<const State_t&
>(earlierState);
307 std::unique_ptr<StateDelta_t> pStateDelta(
new StateDelta_t);
308 pStateDelta->fReadersCountLoc = typedState.fReadersCountLoc;
309 pStateDelta->fDeltaReadersCount = *typedState.fReadersCountLoc - typedState.fReadersCount;
310 pStateDelta->fDeltaWriteRecurse =
fRecurseCounts.fWriteRecurse - typedState.fWriteRecurse;
312 if (pStateDelta->fDeltaReadersCount < 0) {
313 Error(
"TReentrantRWLock::Rewind",
"Inconsistent read lock count!");
317 if (pStateDelta->fDeltaWriteRecurse < 0) {
318 Error(
"TReentrantRWLock::Rewind",
"Inconsistent write lock count!");
322 auto hint =
reinterpret_cast<TVirtualRWMutex::Hint_t *
>(typedState.fReadersCountLoc);
323 if (pStateDelta->fDeltaWriteRecurse != 0) {
325 "Lock rewinded from a thread that does not own the Write lock",
326 fWriter && !fRecurseCounts.IsNotCurrentWriter(local));
329 fRecurseCounts.fWriteRecurse = typedState.fWriteRecurse + 1;
333 Error(
"TReentrantRWLock::Rewind",
"has been called with no write lock held.");
336 if (pStateDelta->fDeltaReadersCount != 0) {
338 *typedState.fReadersCountLoc = typedState.fReadersCount + 1;
345 fReaders = typedState.fReadersCount + 1;
351 return std::unique_ptr<TVirtualRWMutex::StateDelta>(std::move(pStateDelta));
357template <
typename MutexT,
typename RecurseCountsT>
360 Error(
"TReentrantRWLock::Apply",
"Cannot apply empty delta!");
364 using StateDelta_t = TReentrantRWLockStateDelta<MutexT, RecurseCountsT>;
365 const StateDelta_t* typedDelta =
static_cast<const StateDelta_t*
>(state.get());
367 if (typedDelta->fDeltaWriteRecurse < 0) {
368 Error(
"TReentrantRWLock::Apply",
"Negative write recurse count delta!");
371 if (typedDelta->fDeltaReadersCount < 0) {
372 Error(
"TReentrantRWLock::Apply",
"Negative read count delta!");
377 if (typedDelta->fDeltaWriteRecurse != 0) {
379 fRecurseCounts.fWriteRecurse += typedDelta->fDeltaWriteRecurse - 1;
381 if (typedDelta->fDeltaReadersCount != 0) {
384 fReaders += typedDelta->fDeltaReadersCount - 1;
385 *typedDelta->fReadersCountLoc += typedDelta->fDeltaReadersCount - 1;
393template <
typename MutexT,
typename RecurseCountsT>
397 size_t* localReadersCount;
399 std::lock_guard<MutexT> lock(
fMutex);
400 localReadersCount = &(
fRecurseCounts.GetLocalReadersCount(local));
402 if (localReadersCount != presumedLocalReadersCount) {
403 Error(
"TReentrantRWLock::AssertReadCountLocIsFromCurrentThread",
"ReadersCount is from different thread!");
417#ifdef ROOT_CORE_THREAD_TBB
Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.", GetName(), objname)
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
#define R__MAYBE_AssertReadCountLocIsFromCurrentThread(READERSCOUNTLOC)
#define R__MAYBE_ASSERT_WITH_LOCAL_LOCK(where, msg, what)
std::condition_variable_any fCond
! RWlock internal condition variable
void WriteUnLock(TVirtualRWMutex::Hint_t *)
Release the lock in write mode.
TVirtualRWMutex::State State
std::atomic< int > fReaderReservation
! A reader wants access
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.
RecurseCountsT fRecurseCounts
! Trackers for re-entry in the lock by the same thread.
TVirtualRWMutex::Hint_t * WriteLock()
Acquire the lock in write mode.
std::atomic< bool > fWriter
! Is there a writer?
std::atomic< int > fReaders
! Number of readers
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.
MutexT fMutex
! RWlock internal mutex
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.
std::atomic< int > fWriterReservation
! A writer wants access
State as returned by GetStateDelta() that can be passed to Restore().
Earlier lock state as returned by GetState() that can be passed to Restore().