Skip to content

Commit

Permalink
flesh out documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ngoldbaum committed Sep 2, 2024
1 parent 5351baa commit e33212c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 5 deletions.
66 changes: 61 additions & 5 deletions guide/src/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,16 +206,72 @@ PyO3 0.23 introduces preliminary support for the new free-threaded build of
CPython 3.13. PyO3 features that implicitly assumed the existence of the GIL
are not exposed in the free-threaded build, since they are no longer safe.

If you make use of these features then you will need to use conditional
compilation to replace them for extensions built for free-threaded
Python. Extensions built for the free-threaded build will have the
`Py_GIL_DISABLED` attribute defined.
If you make use of these features then you will need to account for the
unavailability of this API in the free-threaded build. One way to handle it is
via conditional compilation -- extensions built for the free-threaded build will
have the `Py_GIL_DISABLED` attribute defined.

### `GILProtected`

`GILProtected` allows mutable access to static data by leveraging the GIL to
lock concurrent access from other threads. In free-threaded python there is no
GIL, so you will need to replace this type with some other form of locking.
GIL, so you will need to replace this type with some other form of locking. In
many cases, `std::sync::Atomic` or `std::sync::Mutex` will be sufficient. If the
locks do not guard the execution of arbitrary Python code or use of the CPython
C API then conditional compilation is likely unnecessary since `GILProtected`
was not needed in the first place.

Before:

```rust,ignore
# use pyo3::prelude::*;
use pyo3::sync::GILProtected;
use pyo3::types::{PyDict, PyNone};
use std::cell::RefCell;
static OBJECTS: GILProtected<RefCell<Vec<Py<PyDict>>>> =
GILProtected::new(RefCell::new(Vec::new()));
fn main() {
Python::with_gil(|py: Python| {
let d = PyDict::new(py);
// stand-in for something that executes arbitrary python code
d.set_item(PyNone::get(py), PyNone::get(py)).unwrap();
OBJECTS.get(py).borrow_mut().push(d.unbind());
});
}
```

After:

```rust
use pyo3::prelude::*;
#[cfg(not(Py_GIL_DISABLED))]
use pyo3::sync::GILProtected;
use pyo3::types::{PyDict, PyNone};
#[cfg(not(Py_GIL_DISABLED))]
use std::cell::RefCell;
#[cfg(Py_GIL_DISABLED)]
use std::sync::Mutex;

#[cfg(not(Py_GIL_DISABLED))]
static OBJECTS: GILProtected<RefCell<Vec<Py<PyDict>>>> =
GILProtected::new(RefCell::new(Vec::new()));
#[cfg(Py_GIL_DISABLED)]
static OBJECTS: Mutex<Vec<Py<PyDict>>> = Mutex::new(Vec::new());

fn main() {
Python::with_gil(|py| {
let d = PyDict::new(py);
// stand-in for something that executes arbitrary python code
d.set_item(PyNone::get(py), PyNone::get(py)).unwrap();
#[cfg(not(Py_GIL_DISABLED))]
OBJECTS.get(py).borrow_mut().push(d.unbind());
#[cfg(Py_GIL_DISABLED)]
OBJECTS.lock().unwrap().push(d.unbind());
});
}
```

</details>

Expand Down
2 changes: 2 additions & 0 deletions src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use crate::PyVisit;
/// It ensures that only one thread at a time can access the inner value via shared references.
/// It can be combined with interior mutability to obtain mutable references.
///
/// This type is not defined for extensions built against the free-threaded CPython ABI.
///
/// # Example
///
/// Combining `GILProtected` with `RefCell` enables mutable access to static data:
Expand Down

0 comments on commit e33212c

Please sign in to comment.