mvdnes/spin-rs

`Once::call_once` doesn't guarantee that the given closure is called only if this is the first time `call_once` has been called.

usamoi opened this issue · 2 comments

This test fails with a certain probability.

// insert this in once.rs:684
    #[test]
    fn extra() {
        use std::sync::Arc;
        use std::sync::atomic::AtomicUsize;
        use std::time::Duration;
        let share = Arc::new(AtomicUsize::new(0));
        let once = Arc::new(Once::<_, Spin>::new());
        let mut hs = Vec::new();
        for _ in 0..10 {
            let h = thread::spawn({
                let share = share.clone();
                let once = once.clone();
                move || {
                    thread::sleep(Duration::from_millis(10));
                    once.call_once(|| {
                        share.fetch_add(1, Ordering::SeqCst);
                    });
                }
            });
            hs.push(h);
        }
        for h in hs {
            let _ = h.join();
        }
        assert_eq!(1, share.load(Ordering::SeqCst));
    }

A typo in https://github.com/mvdnes/spin-rs/blob/master/src/once.rs#L113 makes this bug.
I have made a pull request (#118) to fix it.

This has now been included in the 0.9.3 release.