Skip to content

Commit b958ede

Browse files
committed
Change get's semantics to never block
Turns our, real world code can has **really** subtle bugs with non-blocking semantics
1 parent 5978d18 commit b958ede

File tree

2 files changed

+19
-29
lines changed

2 files changed

+19
-29
lines changed

src/lib.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -659,15 +659,9 @@ pub mod sync {
659659

660660
/// Gets the reference to the underlying value.
661661
///
662-
/// Returns `None` if the cell is empty, or being initialized. This
663-
/// method never blocks.
662+
/// Returns `None` if the cell is empty, or being initialized.
664663
pub fn get(&self) -> Option<&T> {
665-
if self.0.is_initialized() {
666-
// Safe b/c value is initialized.
667-
Some(unsafe { self.get_unchecked() })
668-
} else {
669-
None
670-
}
664+
self.get_or_try_init(|| Err(())).ok()
671665
}
672666

673667
/// Gets the mutable reference to the underlying value.
@@ -787,9 +781,11 @@ pub mod sync {
787781
F: FnOnce() -> Result<T, E>,
788782
{
789783
// Fast path check
790-
if let Some(value) = self.get() {
791-
return Ok(value);
784+
if self.0.is_initialized() {
785+
// Safe b/c value is initialized.
786+
return Ok(unsafe { self.get_unchecked() });
792787
}
788+
793789
self.0.initialize(f)?;
794790

795791
// Safe b/c value is initialized.

tests/test.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -553,25 +553,19 @@ mod sync {
553553
}
554554

555555
#[test]
556-
#[cfg_attr(miri, ignore)] // miri doesn't support Barrier
557-
fn get_does_not_block() {
558-
use std::sync::Barrier;
556+
#[cfg_attr(miri, ignore)]
557+
fn get_blocks() {
558+
static CELL: OnceCell<u32> = OnceCell::new();
559559

560-
let cell = OnceCell::new();
561-
let barrier = Barrier::new(2);
562-
scope(|scope| {
563-
scope.spawn(|_| {
564-
cell.get_or_init(|| {
565-
barrier.wait();
566-
barrier.wait();
567-
"hello".to_string()
568-
});
569-
});
570-
barrier.wait();
571-
assert_eq!(cell.get(), None);
572-
barrier.wait();
573-
})
574-
.unwrap();
575-
assert_eq!(cell.get(), Some(&"hello".to_string()));
560+
let mut thread = None;
561+
562+
let res = *CELL.get_or_init(|| {
563+
thread = Some(std::thread::spawn(|| assert_eq!(CELL.get(), Some(&92))));
564+
std::thread::sleep(std::time::Duration::from_millis(100));
565+
92
566+
});
567+
assert_eq!(res, 92);
568+
569+
thread.unwrap().join().unwrap();
576570
}
577571
}

0 commit comments

Comments
 (0)