@@ -184,24 +184,96 @@ void TReentrantRWLock<MutexT, RecurseCountsT>::WriteUnLock()
184
184
namespace {
185
185
template <typename MutexT, typename RecurseCountsT>
186
186
struct TReentrantRWLockState : public TVirtualMutex ::State {
187
- RecurseCountsT fRecurseCounts ;
187
+ int fReadersCount = 0 ;
188
+ size_t fWriteRecurse = 0 ;
189
+ bool fIsWriter = false ;
188
190
};
189
191
}
190
192
191
193
template <typename MutexT, typename RecurseCountsT>
192
194
std::unique_ptr<TVirtualMutex::State> TReentrantRWLock<MutexT, RecurseCountsT>::Reset()
193
195
{
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
+
195
237
// Do something.
196
- ::Fatal (" Reset()" , " Not implemented, contact pcanal@fnal.gov" );
238
+ // ::Fatal("Reset()", "Not implemented, contact pcanal@fnal.gov");
197
239
return std::move (pState);
198
240
}
199
241
200
242
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 )
202
244
{
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
+
203
275
// Do something.
204
- ::Fatal (" Restore()" , " Not implemented, contact pcanal@fnal.gov" );
276
+ // ::Fatal("Restore()", "Not implemented, contact pcanal@fnal.gov");
205
277
}
206
278
207
279
namespace ROOT {
0 commit comments