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); \
61 ::Fatal(
"UniqueLockRecurseCount Ctor",
"Only one TReentrantRWLock using a UniqueLockRecurseCount is allowed.");
69template <
typename MutexT,
typename RecurseCountsT>
78 auto local = fRecurseCounts.GetLocal();
80 TVirtualRWMutex::Hint_t *
hint =
nullptr;
87 hint = fRecurseCounts.IncrementReadCount(
local, fMutex);
89 }
else if (fRecurseCounts.IsCurrentWriter(
local)) {
96 hint = fRecurseCounts.IncrementReadCount(
local, fMutex);
102 --fReaderReservation;
104 std::unique_lock<MutexT> lock(fMutex);
107 if (fWriter && fRecurseCounts.IsNotCurrentWriter(
local)) {
110 fCond.wait(lock, [
this] {
return !fWriter; });
123 hint = fRecurseCounts.IncrementReadCount(
local);
136template <
typename MutexT,
typename RecurseCountsT>
142 auto local = fRecurseCounts.GetLocal();
143 std::lock_guard<MutexT> lock(fMutex);
150 if (fWriterReservation && fReaders == 0) {
152 std::lock_guard<MutexT> lock(fMutex);
154 --(*localReaderCount);
162 --(*localReaderCount);
168template <
typename MutexT,
typename RecurseCountsT>
171 ++fWriterReservation;
173 std::unique_lock<MutexT> lock(fMutex);
175 auto local = fRecurseCounts.GetLocal();
179 TVirtualRWMutex::Hint_t *
hint =
reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&
readerCount);
184 if (fWriter && fRecurseCounts.IsNotCurrentWriter(
local)) {
190 fCond.wait(lock, [
this] {
return !fWriter; });
195 fRecurseCounts.SetIsWriter(
local);
198 while (fReaderReservation) {
202 fCond.wait(lock, [
this] {
return fReaders == 0; });
207 --fWriterReservation;
216template <
typename MutexT,
typename RecurseCountsT>
220 std::lock_guard<MutexT> lock(fMutex);
222 if (!fWriter || fRecurseCounts.fWriteRecurse == 0) {
223 Error(
"TReentrantRWLock::WriteUnLock",
"Write lock already released for %p",
this);
227 fRecurseCounts.DecrementWriteCount();
229 if (!fRecurseCounts.fWriteRecurse) {
232 auto local = fRecurseCounts.GetLocal();
233 fRecurseCounts.ResetIsWriter(
local);
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>
265 Error(
"TReentrantRWLock::GetStateBefore()",
"Must be write locked!");
269 auto local = fRecurseCounts.GetLocal();
270 if (fRecurseCounts.IsNotCurrentWriter(
local)) {
271 Error(
"TReentrantRWLock::GetStateBefore()",
"Not holding the write lock!");
277 std::lock_guard<MutexT> lock(fMutex);
278 pState->fReadersCountLoc = &(fRecurseCounts.GetLocalReadersCount(
local));
283 pState->fWriteRecurse = fRecurseCounts.fWriteRecurse - 1;
289 return std::unique_ptr<BaseState_t>(
pState.release());
298template <
typename MutexT,
typename RecurseCountsT>
299std::unique_ptr<TVirtualRWMutex::StateDelta>
313 Error(
"TReentrantRWLock::Rewind",
"Inconsistent read lock count!");
318 Error(
"TReentrantRWLock::Rewind",
"Inconsistent write lock count!");
322 auto hint =
reinterpret_cast<TVirtualRWMutex::Hint_t *
>(
typedState.fReadersCountLoc);
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.");
351 return std::unique_ptr<TVirtualRWMutex::StateDelta>(std::move(
pStateDelta));
357template <
typename MutexT,
typename RecurseCountsT>
360 Error(
"TReentrantRWLock::Apply",
"Cannot apply empty delta!");
368 Error(
"TReentrantRWLock::Apply",
"Negative write recurse count delta!");
372 Error(
"TReentrantRWLock::Apply",
"Negative read count delta!");
379 fRecurseCounts.fWriteRecurse +=
typedDelta->fDeltaWriteRecurse - 1;
384 fReaders +=
typedDelta->fDeltaReadersCount - 1;
393template <
typename MutexT,
typename RecurseCountsT>
396 auto local = fRecurseCounts.GetLocal();
399 std::lock_guard<MutexT> lock(fMutex);
403 Error(
"TReentrantRWLock::AssertReadCountLocIsFromCurrentThread",
"ReadersCount is from different thread!");
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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)
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.
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()