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!");
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
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
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
State as returned by GetStateDelta() that can be passed to Restore()
Earlier lock state as returned by GetState() that can be passed to Restore()