diff --git a/core/base/inc/TVirtualRWMutex.h b/core/base/inc/TVirtualRWMutex.h
index abf3eecb3b9eb2eaa3ba723057964e378efe1503..bc6000866ce6d25833e0ee437851983f97aa2ba5 100644
--- a/core/base/inc/TVirtualRWMutex.h
+++ b/core/base/inc/TVirtualRWMutex.h
@@ -44,6 +44,20 @@ public:
    // distinct from these)
    class Hint_t;
 
+   /// \class State
+   /// Earlier lock state as returned by `GetState()` that can be passed to
+   /// `Restore()`
+   struct State {
+      virtual ~State(); // implemented in TVirtualMutex.cxx
+   };
+
+   /// \class StateDelta
+   /// State as returned by `GetStateDelta()` that can be passed to
+   /// `Restore()`
+   struct StateDelta {
+      virtual ~StateDelta(); // implemented in TVirtualMutex.cxx
+   };
+
    virtual Hint_t *ReadLock() = 0;
    virtual void ReadUnLock(Hint_t *) = 0;
    virtual Hint_t *WriteLock() = 0;
@@ -54,6 +68,10 @@ public:
    Int_t UnLock() override { WriteUnLock(nullptr); return 1; }
    Int_t CleanUp() override { WriteUnLock(nullptr); return 1; }
 
+   virtual std::unique_ptr<State> GetState() const = 0;
+   virtual std::unique_ptr<StateDelta> Rewind(const State& earlierState) = 0;
+   virtual void Apply(std::unique_ptr<StateDelta> &&delta) = 0;
+
    TVirtualRWMutex *Factory(Bool_t /*recursive*/ = kFALSE) override = 0;
 
    ClassDefOverride(TVirtualRWMutex, 0)  // Virtual mutex lock class
diff --git a/core/base/src/TVirtualMutex.cxx b/core/base/src/TVirtualMutex.cxx
index 46e14f73a046a69d760d1274933fdb88286177bb..1e7a112aeb172c4648aecf22fd1e95c94c29e1bc 100644
--- a/core/base/src/TVirtualMutex.cxx
+++ b/core/base/src/TVirtualMutex.cxx
@@ -33,6 +33,7 @@ of local objects so it is exception safe.
 */
 
 #include "TVirtualMutex.h"
+#include "TVirtualRWMutex.h"
 
 ClassImp(TVirtualMutex);
 ClassImp(TLockGuard);
@@ -42,3 +43,7 @@ ClassImp(TLockGuard);
 // concept gGlobalMutex must be used in TStorage to prevent
 // lockup of the system (see TMutex::Factory)
 TVirtualMutex *gGlobalMutex = 0;
+
+// From TVirtualRWMutex.h:
+ROOT::TVirtualRWMutex::State::~State() = default;
+ROOT::TVirtualRWMutex::StateDelta::~StateDelta() = default;
\ No newline at end of file
diff --git a/core/thread/src/TRWMutexImp.cxx b/core/thread/src/TRWMutexImp.cxx
index 3607796ea1211461ee7c5826f4148d9eb50a5180..91234d2aa0edee8306aa435dfa5370b3d1fb79e4 100644
--- a/core/thread/src/TRWMutexImp.cxx
+++ b/core/thread/src/TRWMutexImp.cxx
@@ -70,24 +70,37 @@ TVirtualRWMutex *TRWMutexImp<MutexT, RecurseCountsT>::Factory(Bool_t /*recursive
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-/// Reset the mutex state to unlocked. The state before resetting to unlocked is
-/// returned and can be passed to `Restore()` later on. This function must only
-/// be called while the mutex is locked.
+/// Restore the mutex state to the state represented by `state`. This function
+/// must only be called while the mutex is locked. Returns the DeltaState
+/// between now and the rewind point, such that the difference can be re-applied
+/// using `Apply()`.
 
 template <typename MutexT, typename RecurseCountsT>
-std::unique_ptr<TVirtualMutex::State> TRWMutexImp<MutexT, RecurseCountsT>::Reset()
+std::unique_ptr<TVirtualRWMutex::StateDelta>
+TRWMutexImp<MutexT, RecurseCountsT>::Rewind(const TVirtualRWMutex::State &earlierState)
 {
-   return fMutexImp.Reset();
+   return fMutexImp.Rewind(earlierState);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-/// Restore the mutex state to the state pointed to by `state`. This function
-/// must only be called while the mutex is unlocked.
+/// Apply the mutex state delta. This function must only be called while the
+/// mutex is locked.
 
 template <typename MutexT, typename RecurseCountsT>
-void TRWMutexImp<MutexT, RecurseCountsT>::Restore(std::unique_ptr<TVirtualMutex::State> &&state)
+void TRWMutexImp<MutexT, RecurseCountsT>::Apply(std::unique_ptr<TVirtualRWMutex::StateDelta> &&delta)
 {
-   fMutexImp.Restore(std::move(state));
+   fMutexImp.Apply(std::move(delta));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Get the mutex state. This function must only be called while the mutex is
+/// locked.
+
+template <typename MutexT, typename RecurseCountsT>
+std::unique_ptr<TVirtualRWMutex::State>
+TRWMutexImp<MutexT, RecurseCountsT>::GetState() const
+{
+   return fMutexImp.GetState();
 }
 
 template class TRWMutexImp<TMutex>;
diff --git a/core/thread/src/TRWMutexImp.h b/core/thread/src/TRWMutexImp.h
index bd77c69e3956736db0c759113a58079a02edbc04..5b9dd11e7e58656067dfcbd398fc9d357ff0328e 100644
--- a/core/thread/src/TRWMutexImp.h
+++ b/core/thread/src/TRWMutexImp.h
@@ -29,8 +29,9 @@ public:
    void WriteUnLock(Hint_t *) override;
 
    TVirtualRWMutex *Factory(Bool_t /*recursive*/ = kFALSE) override;
-   std::unique_ptr<TVirtualMutex::State> Reset() override;
-   void Restore(std::unique_ptr<TVirtualMutex::State> &&) override;
+   std::unique_ptr<State> GetState() const override;
+   std::unique_ptr<StateDelta> Rewind(const State &earlierState) override;
+   void Apply(std::unique_ptr<StateDelta> &&delta) override;
 
    ClassDefInlineOverride(TRWMutexImp,0)  // Concrete RW mutex lock class
 };