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>
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)) {
108 auto readerCount = fRecurseCounts.GetLocalReadersCount(local);
109 if (readerCount == 0)
110 fCond.wait(lock, [
this] {
return !fWriter; });
123 hint = fRecurseCounts.IncrementReadCount(local);
136template <
typename MutexT,
typename RecurseCountsT>
139 size_t *localReaderCount;
142 auto local = fRecurseCounts.GetLocal();
143 std::lock_guard<MutexT> lock(fMutex);
144 localReaderCount = &(fRecurseCounts.GetLocalReadersCount(local));
146 localReaderCount =
reinterpret_cast<size_t*
>(hint);
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();
178 auto &readerCount = fRecurseCounts.GetLocalReadersCount(local);
179 TVirtualRWMutex::Hint_t *hint =
reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&readerCount);
181 fReaders -= readerCount;
184 if (fWriter && fRecurseCounts.IsNotCurrentWriter(local)) {
185 if (readerCount && fReaders == 0) {
190 fCond.wait(lock, [
this] {
return !fWriter; });
195 fRecurseCounts.SetIsWriter(local);
198 while (fReaderReservation) {
202 fCond.wait(lock, [
this] {
return fReaders == 0; });
205 fReaders += readerCount;
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>
262 using State_t = TReentrantRWLockState<MutexT, RecurseCountsT>;
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!");
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);
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>
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>
396 auto local = fRecurseCounts.GetLocal();
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)
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()