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