Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Py::drop_ref method #3871

Merged
merged 7 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/3871.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `Py::drop_ref` to explicitly drop a `Py`` and immediately decrease the Python reference count if the GIL is already held.
33 changes: 33 additions & 0 deletions src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,10 @@ impl<T> IntoPy<PyObject> for Borrowed<'_, '_, T> {
/// Otherwise, the reference count will be decreased the next time the GIL is
/// reacquired.
///
/// If you happen to be already holding the GIL, [`Py::drop_ref`] will decrease
/// the Python reference count immediately and will execute slightly faster than
/// relying on implicit [`Drop`]s.
///
/// # A note on `Send` and `Sync`
///
/// Accessing this object is threadsafe, since any access to its API requires a [`Python<'py>`](crate::Python) token.
Expand Down Expand Up @@ -1215,6 +1219,35 @@ impl<T> Py<T> {
unsafe { Py::from_borrowed_ptr(py, self.0.as_ptr()) }
}

/// Drops `self` and immediately decreases its reference count.
///
/// This method is a micro-optimisation over [`Drop`] if you happen to be holding the GIL
/// already.
juntyr marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Examples
///
/// ```rust
/// use pyo3::prelude::*;
/// use pyo3::types::PyDict;
///
/// # fn main() {
/// Python::with_gil(|py| {
/// let object: Py<PyDict> = PyDict::new_bound(py).unbind();
///
/// // some usage of object
///
/// object.drop_ref(py);
/// });
/// # }
/// ```
#[inline]
pub fn drop_ref(self, py: Python<'_>) {
let _py = py;

// Safety: we hold the GIL and forget `self` to not trigger a double free
unsafe { pyo3::ffi::Py_DECREF(self.into_ptr()) };
juntyr marked this conversation as resolved.
Show resolved Hide resolved
}

/// Returns whether the object is considered to be None.
///
/// This is equivalent to the Python expression `self is None`.
Expand Down
Loading