| #[cfg(feature = "std")] |
| use std::sync::Barrier; |
| use std::{ |
| num::NonZeroUsize, |
| sync::atomic::{AtomicUsize, Ordering::SeqCst}, |
| thread::scope, |
| }; |
| |
| use once_cell::race::{OnceBool, OnceNonZeroUsize}; |
| |
| #[test] |
| fn once_non_zero_usize_smoke_test() { |
| let cnt = AtomicUsize::new(0); |
| let cell = OnceNonZeroUsize::new(); |
| let val = NonZeroUsize::new(92).unwrap(); |
| scope(|s| { |
| s.spawn(|| { |
| assert_eq!( |
| cell.get_or_init(|| { |
| cnt.fetch_add(1, SeqCst); |
| val |
| }), |
| val |
| ); |
| assert_eq!(cnt.load(SeqCst), 1); |
| |
| assert_eq!( |
| cell.get_or_init(|| { |
| cnt.fetch_add(1, SeqCst); |
| val |
| }), |
| val |
| ); |
| assert_eq!(cnt.load(SeqCst), 1); |
| }); |
| }); |
| assert_eq!(cell.get(), Some(val)); |
| assert_eq!(cnt.load(SeqCst), 1); |
| } |
| |
| #[test] |
| fn once_non_zero_usize_set() { |
| let val1 = NonZeroUsize::new(92).unwrap(); |
| let val2 = NonZeroUsize::new(62).unwrap(); |
| |
| let cell = OnceNonZeroUsize::new(); |
| |
| assert!(cell.set(val1).is_ok()); |
| assert_eq!(cell.get(), Some(val1)); |
| |
| assert!(cell.set(val2).is_err()); |
| assert_eq!(cell.get(), Some(val1)); |
| } |
| |
| #[cfg(feature = "std")] |
| #[test] |
| fn once_non_zero_usize_first_wins() { |
| let val1 = NonZeroUsize::new(92).unwrap(); |
| let val2 = NonZeroUsize::new(62).unwrap(); |
| |
| let cell = OnceNonZeroUsize::new(); |
| |
| let b1 = Barrier::new(2); |
| let b2 = Barrier::new(2); |
| let b3 = Barrier::new(2); |
| scope(|s| { |
| s.spawn(|| { |
| let r1 = cell.get_or_init(|| { |
| b1.wait(); |
| b2.wait(); |
| val1 |
| }); |
| assert_eq!(r1, val1); |
| b3.wait(); |
| }); |
| b1.wait(); |
| s.spawn(|| { |
| let r2 = cell.get_or_init(|| { |
| b2.wait(); |
| b3.wait(); |
| val2 |
| }); |
| assert_eq!(r2, val1); |
| }); |
| }); |
| |
| assert_eq!(cell.get(), Some(val1)); |
| } |
| |
| #[test] |
| fn once_bool_smoke_test() { |
| let cnt = AtomicUsize::new(0); |
| let cell = OnceBool::new(); |
| scope(|s| { |
| s.spawn(|| { |
| assert_eq!( |
| cell.get_or_init(|| { |
| cnt.fetch_add(1, SeqCst); |
| false |
| }), |
| false |
| ); |
| assert_eq!(cnt.load(SeqCst), 1); |
| |
| assert_eq!( |
| cell.get_or_init(|| { |
| cnt.fetch_add(1, SeqCst); |
| false |
| }), |
| false |
| ); |
| assert_eq!(cnt.load(SeqCst), 1); |
| }); |
| }); |
| assert_eq!(cell.get(), Some(false)); |
| assert_eq!(cnt.load(SeqCst), 1); |
| } |
| |
| #[test] |
| fn once_bool_set() { |
| let cell = OnceBool::new(); |
| |
| assert!(cell.set(false).is_ok()); |
| assert_eq!(cell.get(), Some(false)); |
| |
| assert!(cell.set(true).is_err()); |
| assert_eq!(cell.get(), Some(false)); |
| } |