Skip to content

Commit 4deb81d

Browse files
committed
Implement TReentrantRWLock::Reset/Restore
1 parent 5db13c6 commit 4deb81d

File tree

1 file changed

+77
-5
lines changed

1 file changed

+77
-5
lines changed

core/thread/src/TReentrantRWLock.cxx

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,24 +184,96 @@ void TReentrantRWLock<MutexT, RecurseCountsT>::WriteUnLock()
184184
namespace {
185185
template <typename MutexT, typename RecurseCountsT>
186186
struct TReentrantRWLockState: public TVirtualMutex::State {
187-
RecurseCountsT fRecurseCounts;
187+
int fReadersCount = 0;
188+
size_t fWriteRecurse = 0;
189+
bool fIsWriter = false;
188190
};
189191
}
190192

191193
template <typename MutexT, typename RecurseCountsT>
192194
std::unique_ptr<TVirtualMutex::State> TReentrantRWLock<MutexT, RecurseCountsT>::Reset()
193195
{
194-
std::unique_ptr<TReentrantRWLockState<MutexT, RecurseCountsT>> pState;
196+
using State_t = TReentrantRWLockState<MutexT, RecurseCountsT>;
197+
198+
std::unique_ptr<State_t> pState(new State_t);
199+
auto local = fRecurseCounts.GetLocal();
200+
201+
size_t readerCount;
202+
{
203+
std::unique_lock<MutexT> lock(fMutex);
204+
readerCount = fRecurseCounts.GetLocalReadersCount(local);
205+
}
206+
207+
pState->fReadersCount = readerCount;
208+
209+
if (fWriter && !fRecurseCounts.IsNotCurrentWriter(local)) {
210+
211+
// We are holding the write lock.
212+
pState->fIsWriter = true;
213+
pState->fWriteRecurse = fRecurseCounts.fWriteRecurse;
214+
215+
// Now set the lock (and potential read locks) for immediate release.
216+
fReaders -= readerCount;
217+
fRecurseCounts.fWriteRecurse = 1;
218+
// insertion in the reader count can only happen during a ReadLock
219+
// which can not execute until we release the write lock, so no
220+
// need to take the local mutex here.
221+
fRecurseCounts.ResetReadCount(local, 0);
222+
223+
// Release this thread's write lock
224+
WriteUnLock();
225+
} else if (readerCount) {
226+
// Now set the lock for release.
227+
{
228+
std::unique_lock<MutexT> lock(fMutex);
229+
fReaders -= (readerCount-1);
230+
fRecurseCounts.ResetReadCount(local, 1);
231+
}
232+
233+
// Release this thread's reader lock(s)
234+
ReadUnLock();
235+
}
236+
195237
// Do something.
196-
::Fatal("Reset()", "Not implemented, contact pcanal@fnal.gov");
238+
//::Fatal("Reset()", "Not implemented, contact pcanal@fnal.gov");
197239
return std::move(pState);
198240
}
199241

200242
template <typename MutexT, typename RecurseCountsT>
201-
void TReentrantRWLock<MutexT, RecurseCountsT>::Restore(std::unique_ptr<TVirtualMutex::State> &&)
243+
void TReentrantRWLock<MutexT, RecurseCountsT>::Restore(std::unique_ptr<TVirtualMutex::State> &&state)
202244
{
245+
TReentrantRWLockState<MutexT, RecurseCountsT> *pState = dynamic_cast<TReentrantRWLockState<MutexT, RecurseCountsT> *>(state.get());
246+
if (!pState) {
247+
if (state) {
248+
SysError("Restore", "LOGIC ERROR - invalid state object!");
249+
return;
250+
}
251+
// No state, do nothing.
252+
return;
253+
}
254+
255+
if (pState->fIsWriter) {
256+
WriteLock();
257+
// Now that we go the lock, fix up the recursion count.
258+
std::unique_lock<MutexT> lock(fMutex);
259+
fRecurseCounts.fWriteRecurse = pState->fWriteRecurse;
260+
auto local = fRecurseCounts.GetLocal();
261+
fRecurseCounts.ResetReadCount(local, pState->fReadersCount);
262+
fReaders += pState->fReadersCount;
263+
} else {
264+
ReadLock();
265+
// Now that we go the read lock, fix up the local recursion count.
266+
assert( pState->fReadersCount >= 1 );
267+
auto readerCount = pState->fReadersCount;
268+
269+
std::unique_lock<MutexT> lock(fMutex);
270+
auto local = fRecurseCounts.GetLocal();
271+
fRecurseCounts.ResetReadCount(local, readerCount);
272+
fReaders += readerCount - 1;
273+
}
274+
203275
// Do something.
204-
::Fatal("Restore()", "Not implemented, contact pcanal@fnal.gov");
276+
//::Fatal("Restore()", "Not implemented, contact pcanal@fnal.gov");
205277
}
206278

207279
namespace ROOT {

0 commit comments

Comments
 (0)