12 use pyo3::types::{PyBytes, PyBytesMethods, PyList}; |
12 use pyo3::types::{PyBytes, PyBytesMethods, PyList}; |
13 use pyo3_sharedref::PyShareable; |
13 use pyo3_sharedref::PyShareable; |
14 |
14 |
15 use std::sync::{ |
15 use std::sync::{ |
16 atomic::{AtomicUsize, Ordering}, |
16 atomic::{AtomicUsize, Ordering}, |
17 RwLock, RwLockReadGuard, |
17 RwLock, RwLockReadGuard, RwLockWriteGuard, |
18 }; |
18 }; |
19 |
19 |
20 use hg::{ |
20 use hg::{ |
21 revlog::{ |
21 revlog::{ |
22 index::Index, |
22 index::Index, |
256 let shareable_ref = unsafe { self_ref.irl.borrow_with_owner(slf) }; |
256 let shareable_ref = unsafe { self_ref.irl.borrow_with_owner(slf) }; |
257 let guard = shareable_ref.try_read().map_err(map_try_lock_error)?; |
257 let guard = shareable_ref.try_read().map_err(map_try_lock_error)?; |
258 f(&self_ref, guard) |
258 f(&self_ref, guard) |
259 } |
259 } |
260 |
260 |
|
261 #[allow(dead_code)] |
|
262 /// Take the lock on `slf.irl` for writing and call a closure. |
|
263 /// |
|
264 /// See [`Self::with_core_read`] for more explanations. |
|
265 fn with_core_write<'py, T>( |
|
266 slf: &Bound<'py, Self>, |
|
267 f: impl FnOnce( |
|
268 &PyRef<'py, Self>, |
|
269 RwLockWriteGuard<CoreInnerRevlog>, |
|
270 ) -> PyResult<T>, |
|
271 ) -> PyResult<T> { |
|
272 let self_ref = slf.borrow(); |
|
273 // Safety: the owner is the right one. We will anyway |
|
274 // not actually `share` it. Perhaps pyo3-sharedref should provide |
|
275 // something less scary for this kind of usage. |
|
276 let shareable_ref = unsafe { self_ref.irl.borrow_with_owner(slf) }; |
|
277 let guard = shareable_ref.try_write().map_err(map_try_lock_error)?; |
|
278 f(&self_ref, guard) |
|
279 } |
|
280 |
261 fn with_index_read<T>( |
281 fn with_index_read<T>( |
262 slf: &Bound<'_, Self>, |
282 slf: &Bound<'_, Self>, |
263 f: impl FnOnce(&Index) -> PyResult<T>, |
283 f: impl FnOnce(&Index) -> PyResult<T>, |
264 ) -> PyResult<T> { |
284 ) -> PyResult<T> { |
265 Self::with_core_read(slf, |_, guard| f(&guard.index)) |
285 Self::with_core_read(slf, |_, guard| f(&guard.index)) |
|
286 } |
|
287 |
|
288 #[allow(dead_code)] |
|
289 fn with_index_write<T>( |
|
290 slf: &Bound<'_, Self>, |
|
291 f: impl FnOnce(&mut Index) -> PyResult<T>, |
|
292 ) -> PyResult<T> { |
|
293 Self::with_core_write(slf, |_, mut guard| f(&mut guard.index)) |
266 } |
294 } |
267 |
295 |
268 /// Lock `slf` for reading and execute a closure on its [`Index`] and |
296 /// Lock `slf` for reading and execute a closure on its [`Index`] and |
269 /// [`NodeTree`] |
297 /// [`NodeTree`] |
270 /// |
298 /// |
276 Self::with_core_read(slf, |self_ref, guard| { |
304 Self::with_core_read(slf, |self_ref, guard| { |
277 let idx = &guard.index; |
305 let idx = &guard.index; |
278 let nt = |
306 let nt = |
279 self_ref.get_nodetree(idx)?.read().map_err(map_lock_error)?; |
307 self_ref.get_nodetree(idx)?.read().map_err(map_lock_error)?; |
280 let nt = nt.as_ref().expect("nodetree should be set"); |
308 let nt = nt.as_ref().expect("nodetree should be set"); |
|
309 f(idx, nt) |
|
310 }) |
|
311 } |
|
312 |
|
313 #[allow(dead_code)] |
|
314 fn with_index_nt_write<T>( |
|
315 slf: &Bound<'_, Self>, |
|
316 f: impl FnOnce(&mut Index, &mut CoreNodeTree) -> PyResult<T>, |
|
317 ) -> PyResult<T> { |
|
318 Self::with_core_write(slf, |self_ref, mut guard| { |
|
319 let idx = &mut guard.index; |
|
320 let mut nt = self_ref |
|
321 .get_nodetree(idx)? |
|
322 .write() |
|
323 .map_err(map_lock_error)?; |
|
324 let nt = nt.as_mut().expect("nodetree should be set"); |
281 f(idx, nt) |
325 f(idx, nt) |
282 }) |
326 }) |
283 } |
327 } |
284 |
328 |
285 /// Fill a [`CoreNodeTree`] by doing a full iteration on the given |
329 /// Fill a [`CoreNodeTree`] by doing a full iteration on the given |