Skip to content

Commit

Permalink
Separate the fast and slow path of GILOnceCell::get_or_init.
Browse files Browse the repository at this point in the history
  • Loading branch information
adamreichold committed Apr 3, 2022
1 parent d825c04 commit c0fc940
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/once_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,23 @@ impl<T> GILOnceCell<T> {
/// exactly once, even if multiple threads attempt to call `get_or_init`
/// 4) if f() can panic but still does not release the GIL, it may be called multiple times,
/// but it is guaranteed that f() will never be called concurrently
#[inline]
pub fn get_or_init<F>(&self, py: Python<'_>, f: F) -> &T
where
F: FnOnce() -> T,
{
let inner = unsafe { &*self.0.get() }.as_ref();
if let Some(value) = inner {
if let Some(value) = self.get(py) {
return value;
}

self.init(py, f)
}

#[cold]
fn init<F>(&self, py: Python<'_>, f: F) -> &T
where
F: FnOnce() -> T,
{
// Note that f() could temporarily release the GIL, so it's possible that another thread
// writes to this GILOnceCell before f() finishes. That's fine; we'll just have to discard
// the value computed here and accept a bit of wasted computation.
Expand Down

0 comments on commit c0fc940

Please sign in to comment.