changeset 52788:e29e75e8328c

rust-pyo3-revlog: index and notetree writing accessors It works in the same way as their reading counterparts, given that we are leveraging the inner mutability of the `PyShareable` for the index and of the main object for the nodetree.
author Georges Racinet <georges.racinet@cloudcrane.io>
date Wed, 25 Dec 2024 17:17:40 +0100
parents e5f89bd1a5ee
children 34f44aa5e844
files rust/hg-pyo3/src/revlog/mod.rs
diffstat 1 files changed, 45 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/rust/hg-pyo3/src/revlog/mod.rs	Wed Dec 25 17:15:35 2024 +0100
+++ b/rust/hg-pyo3/src/revlog/mod.rs	Wed Dec 25 17:17:40 2024 +0100
@@ -14,7 +14,7 @@
 
 use std::sync::{
     atomic::{AtomicUsize, Ordering},
-    RwLock, RwLockReadGuard,
+    RwLock, RwLockReadGuard, RwLockWriteGuard,
 };
 
 use hg::{
@@ -258,6 +258,26 @@
         f(&self_ref, guard)
     }
 
+    #[allow(dead_code)]
+    /// Take the lock on `slf.irl` for writing and call a closure.
+    ///
+    /// See [`Self::with_core_read`] for more explanations.
+    fn with_core_write<'py, T>(
+        slf: &Bound<'py, Self>,
+        f: impl FnOnce(
+            &PyRef<'py, Self>,
+            RwLockWriteGuard<CoreInnerRevlog>,
+        ) -> PyResult<T>,
+    ) -> PyResult<T> {
+        let self_ref = slf.borrow();
+        // Safety: the owner is the right one. We will anyway
+        // not actually `share` it. Perhaps pyo3-sharedref should provide
+        // something less scary for this kind of usage.
+        let shareable_ref = unsafe { self_ref.irl.borrow_with_owner(slf) };
+        let guard = shareable_ref.try_write().map_err(map_try_lock_error)?;
+        f(&self_ref, guard)
+    }
+
     fn with_index_read<T>(
         slf: &Bound<'_, Self>,
         f: impl FnOnce(&Index) -> PyResult<T>,
@@ -265,6 +285,14 @@
         Self::with_core_read(slf, |_, guard| f(&guard.index))
     }
 
+    #[allow(dead_code)]
+    fn with_index_write<T>(
+        slf: &Bound<'_, Self>,
+        f: impl FnOnce(&mut Index) -> PyResult<T>,
+    ) -> PyResult<T> {
+        Self::with_core_write(slf, |_, mut guard| f(&mut guard.index))
+    }
+
     /// Lock `slf` for reading and execute a closure on its [`Index`] and
     /// [`NodeTree`]
     ///
@@ -282,6 +310,22 @@
         })
     }
 
+    #[allow(dead_code)]
+    fn with_index_nt_write<T>(
+        slf: &Bound<'_, Self>,
+        f: impl FnOnce(&mut Index, &mut CoreNodeTree) -> PyResult<T>,
+    ) -> PyResult<T> {
+        Self::with_core_write(slf, |self_ref, mut guard| {
+            let idx = &mut guard.index;
+            let mut nt = self_ref
+                .get_nodetree(idx)?
+                .write()
+                .map_err(map_lock_error)?;
+            let nt = nt.as_mut().expect("nodetree should be set");
+            f(idx, nt)
+        })
+    }
+
     /// Fill a [`CoreNodeTree`] by doing a full iteration on the given
     /// [`Index`]
     ///