Struct pyo3::sync::GILOnceCell
source · pub struct GILOnceCell<T>(/* private fields */);Expand description
A write-once cell similar to once_cell::OnceCell.
Unlike once_cell::sync which blocks threads to achieve thread safety, this implementation
uses the Python GIL to mediate concurrent access. This helps in cases where once_cell or
lazy_static’s synchronization strategy can lead to deadlocks when interacting with the Python
GIL. For an example, see the FAQ section of the guide.
Note that:
get_or_initandget_or_try_initdo not protect against infinite recursion from reentrant initialization.- If the initialization function
fprovided toget_or_init(orget_or_try_init) temporarily releases the GIL (e.g. by callingPython::import) then it is possible for a second thread to also begin initializing theGITOnceCell. Even when this happensGILOnceCellguarantees that only one write to the cell ever occurs- this is treated as a race, other threads will discard the value they compute and return the result of the first complete computation.
Examples
The following example shows how to use GILOnceCell to share a reference to a Python list
between threads:
use pyo3::sync::GILOnceCell;
use pyo3::prelude::*;
use pyo3::types::PyList;
static LIST_CELL: GILOnceCell<Py<PyList>> = GILOnceCell::new();
pub fn get_shared_list(py: Python<'_>) -> &PyList {
LIST_CELL
.get_or_init(py, || PyList::empty(py).into())
.as_ref(py)
}Implementations§
source§impl<T> GILOnceCell<T>
impl<T> GILOnceCell<T>
sourcepub fn get(&self, _py: Python<'_>) -> Option<&T>
pub fn get(&self, _py: Python<'_>) -> Option<&T>
Get a reference to the contained value, or None if the cell has not yet been written.
sourcepub fn get_or_init<F>(&self, py: Python<'_>, f: F) -> &Twhere
F: FnOnce() -> T,
pub fn get_or_init<F>(&self, py: Python<'_>, f: F) -> &Twhere F: FnOnce() -> T,
Get a reference to the contained value, initializing it if needed using the provided closure.
See the type-level documentation for detail on re-entrancy and concurrent initialization.
sourcepub fn get_or_try_init<F, E>(&self, py: Python<'_>, f: F) -> Result<&T, E>where
F: FnOnce() -> Result<T, E>,
pub fn get_or_try_init<F, E>(&self, py: Python<'_>, f: F) -> Result<&T, E>where F: FnOnce() -> Result<T, E>,
Like get_or_init, but accepts a fallible initialization function. If it fails, the cell
is left uninitialized.
See the type-level documentation for detail on re-entrancy and concurrent initialization.