Mercurial > public > mercurial-scm > hg-stable
changeset 52555:1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Depending on the caller context, we might have a `Python<'py>`
around or any of the smart pointers that bear the GIL lifetime.
Of course, all of these can give back a `Python<'py>` but it is
worthwile to reduce the needed boilerplate.
The trait just expresses that a lifetime is assumed to be outlived
by the PyO3 GIL lifetime. It is marked as unsafe because that is
just trusting the implementor.
A first version of this was made of a safe trait with a `get_py()` method
and the corresponding trivial implementations. We found it finally to be
even more artificial, as it boils down to coding 4 functions
doing and returning no real data, that we hope the compiler
will optimize away.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Mon, 09 Dec 2024 09:38:57 +0100 |
parents | 64a618048ba8 |
children | bd65cb043aa5 |
files | rust/hg-pyo3/src/convert_cpython.rs |
diffstat | 1 files changed, 22 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-pyo3/src/convert_cpython.rs Sat Dec 07 18:05:47 2024 +0100 +++ b/rust/hg-pyo3/src/convert_cpython.rs Mon Dec 09 09:38:57 2024 +0100 @@ -11,6 +11,7 @@ //! the arguments side of function signatures when they are not simply elided. use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; +use pyo3::{pyclass::boolean_struct::False, PyClass}; use cpython::ObjectProtocol; use cpython::PythonObject; @@ -19,6 +20,23 @@ use hg::revlog::index::Index as CoreIndex; use rusthg::revlog::{InnerRevlog, PySharedIndex}; +/// Marker trait for PyO3 objects with a lifetime representing the acquired GIL +/// +/// # Safety +/// +/// This trait must not be implemented for objects with lifetimes that +/// do not imply in PyO3 that the GIL is acquired during the whole lifetime. +pub unsafe trait WithGIL<'py> {} + +// Safety: the lifetime on these PyO3 objects all represent the acquired GIL +unsafe impl<'py> WithGIL<'py> for Python<'py> {} +unsafe impl<'py, T> WithGIL<'py> for Bound<'py, T> {} +unsafe impl<'py, T: PyClass> WithGIL<'py> for PyRef<'py, T> {} +unsafe impl<'py, T: PyClass<Frozen = False>> WithGIL<'py> + for PyRefMut<'py, T> +{ +} + /// Force cpython's GIL handle with the appropriate lifetime /// /// In `pyo3`, the fact that we have the GIL is expressed by the lifetime of @@ -31,10 +49,11 @@ /// already has it works) *as long as it is properly released* /// reference: /// <https://docs.python.org/3.8/c-api/init.html#c.PyGILState_Ensure> -pub(crate) fn cpython_handle<'py, T>( - _bound: &Bound<'py, T>, +pub(crate) fn cpython_handle<'py, T: WithGIL<'py>>( + _with_gil: &T, ) -> cpython::Python<'py> { - // safety: this is safe because the returned object has the 'py lifetime + // safety: this is safe because the returned object has the same lifetime + // as the incoming object. unsafe { cpython::Python::assume_gil_acquired() } }