13 #ifndef ROOT_TReentrantRWLock 
   14 #define ROOT_TReentrantRWLock 
   21 #include <condition_variable> 
   23 #include <unordered_map> 
   27 struct UniqueLockRecurseCount {
 
   28    using Hint_t = TVirtualRWMutex::Hint_t;
 
   31       size_t fReadersCount = 0;
 
   32       bool fIsWriter = 
false;
 
   34    size_t fWriteRecurse = 0; 
 
   36    UniqueLockRecurseCount();
 
   38    using local_t = LocalCounts*;
 
   41       TTHREAD_TLS_DECL(LocalCounts, gLocal);
 
   45    Hint_t *IncrementReadCount(local_t &local) {
 
   46       ++(local->fReadersCount);
 
   47       return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
 
   50    template <
typename MutexT>
 
   51    Hint_t *IncrementReadCount(local_t &local, MutexT &) {
 
   52       return IncrementReadCount(local);
 
   55    Hint_t *DecrementReadCount(local_t &local) {
 
   56       --(local->fReadersCount);
 
   57       return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&(local->fReadersCount));
 
   60    template <
typename MutexT>
 
   61    Hint_t *DecrementReadCount(local_t &local, MutexT &) {
 
   62       return DecrementReadCount(local);
 
   65    void ResetReadCount(local_t &local, 
int newvalue) {
 
   66       local->fReadersCount = newvalue;
 
   69    bool IsCurrentWriter(local_t &local) { 
return local->fIsWriter; }
 
   70    bool IsNotCurrentWriter(local_t &local) { 
return !local->fIsWriter; }
 
   72    void SetIsWriter(local_t &local)
 
   78       local->fIsWriter = 
true;
 
   81    void DecrementWriteCount() { --fWriteRecurse; }
 
   83    void ResetIsWriter(local_t &local) { local->fIsWriter = 
false; }
 
   85    size_t &GetLocalReadersCount(local_t &local) { 
return local->fReadersCount; }
 
   88 struct RecurseCounts {
 
   89    using Hint_t = TVirtualRWMutex::Hint_t;
 
   90    using ReaderColl_t = std::unordered_map<std::thread::id, size_t>;
 
   93    std::thread::id fWriterThread; 
 
   94    ReaderColl_t fReadersCount;    
 
   96    using local_t = std::thread::id;
 
   98    local_t GetLocal()
 const { 
return std::this_thread::get_id(); }
 
  100    Hint_t *IncrementReadCount(local_t &local) {
 
  101       auto &count = fReadersCount[local];
 
  103       return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&count);
 
  106    template <
typename MutexT>
 
  107    Hint_t *IncrementReadCount(local_t &local, MutexT &mutex)
 
  109       std::unique_lock<MutexT> lock(mutex);
 
  110       return IncrementReadCount(local);
 
  113    Hint_t *DecrementReadCount(local_t &local) {
 
  114       auto &count = fReadersCount[local];
 
  116       return reinterpret_cast<TVirtualRWMutex::Hint_t *
>(&count);
 
  119    template <
typename MutexT>
 
  120    Hint_t *DecrementReadCount(local_t &local, MutexT &mutex)
 
  122       std::unique_lock<MutexT> lock(mutex);
 
  123       return DecrementReadCount(local);
 
  126    void ResetReadCount(local_t &local, 
int newvalue) {
 
  127       fReadersCount[local] = newvalue;
 
  130    bool IsCurrentWriter(local_t &local)
 const { 
return fWriterThread == local; }
 
  131    bool IsNotCurrentWriter(local_t &local)
 const { 
return fWriterThread != local; }
 
  133    void SetIsWriter(local_t &local)
 
  139       fWriterThread = local;
 
  142    void DecrementWriteCount() { --fWriteRecurse; }
 
  144    void ResetIsWriter(local_t & ) { fWriterThread = std::thread::id(); }
 
  146    size_t &GetLocalReadersCount(local_t &local) { 
return fReadersCount[local]; }
 
  152 template <
typename MutexT = ROOT::TSpinMutex, 
typename RecurseCountsT = Internal::RecurseCounts>
 
  153 class TReentrantRWLock {
 
  156    std::atomic<int> fReaders;           
 
  157    std::atomic<int> fReaderReservation; 
 
  158    std::atomic<int> fWriterReservation; 
 
  159    std::atomic<bool> fWriter;           
 
  161    std::condition_variable_any fCond;   
 
  163    RecurseCountsT fRecurseCounts;        
 
  170    void AssertReadCountLocIsFromCurrentThread(
const size_t* presumedLocalReadersCount);
 
  173    using State = TVirtualRWMutex::State;
 
  174    using StateDelta = TVirtualRWMutex::StateDelta;
 
  178    TReentrantRWLock() : fReaders(0), fReaderReservation(0), fWriterReservation(0), fWriter(false) {}
 
  180    TVirtualRWMutex::Hint_t *ReadLock();
 
  181    void ReadUnLock(TVirtualRWMutex::Hint_t *);
 
  182    TVirtualRWMutex::Hint_t *WriteLock();
 
  183    void WriteUnLock(TVirtualRWMutex::Hint_t *);
 
  185    std::unique_ptr<State> GetStateBefore();
 
  186    std::unique_ptr<StateDelta> Rewind(
const State &earlierState);
 
  187    void Apply(std::unique_ptr<StateDelta> &&delta);