The py_capsule! and py_capsule_fn! macros generate retrieve functions that cache their results for subsequent calls.
Prior to this commit, caching is done with a generated unsafe static mut item whose access is made thread-safe by a std::sync::Once on the side. However this synchronization is unnecessary since retreive takes a Python<'_> parameter that indicates that the GIL is held.
This changes the cache to use safe static item instead, with GILProtected for synchronization-free thread-safety and OnceCell for interior mutability. As a bonus, this removes the need for cache-related unsafe code in generated retrieve functions.
The
py_capsule!
andpy_capsule_fn!
macros generateretrieve
functions that cache their results for subsequent calls.Prior to this commit, caching is done with a generated unsafe
static mut
item whose access is made thread-safe by astd::sync::Once
on the side. However this synchronization is unnecessary sinceretreive
takes aPython<'_>
parameter that indicates that the GIL is held.This changes the cache to use safe
static
item instead, withGILProtected
for synchronization-free thread-safety andOnceCell
for interior mutability. As a bonus, this removes the need for cache-relatedunsafe
code in generatedretrieve
functions.This adds a dependency to the
once_cell
crate, which can be removed whenOnceCell
becomes stable in the standard library: https://github.com/rust-lang/rust/issues/74465Alternatively
OnceCell
could be replaced withUnsafeCell
plus someunsafe
code, effectively inlining the core of the logic ofOnceCell
.Fixes https://github.com/dgrunwald/rust-cpython/issues/263