1 #[cfg(feature = "std")]
2 use std::sync::Barrier;
3 use std::{
4     num::NonZeroUsize,
5     sync::atomic::{AtomicUsize, Ordering::SeqCst},
6     thread::scope,
7 };
8 
9 use once_cell::race::{OnceBool, OnceNonZeroUsize};
10 
11 #[test]
once_non_zero_usize_smoke_test()12 fn once_non_zero_usize_smoke_test() {
13     let cnt = AtomicUsize::new(0);
14     let cell = OnceNonZeroUsize::new();
15     let val = NonZeroUsize::new(92).unwrap();
16     scope(|s| {
17         s.spawn(|| {
18             assert_eq!(
19                 cell.get_or_init(|| {
20                     cnt.fetch_add(1, SeqCst);
21                     val
22                 }),
23                 val
24             );
25             assert_eq!(cnt.load(SeqCst), 1);
26 
27             assert_eq!(
28                 cell.get_or_init(|| {
29                     cnt.fetch_add(1, SeqCst);
30                     val
31                 }),
32                 val
33             );
34             assert_eq!(cnt.load(SeqCst), 1);
35         });
36     });
37     assert_eq!(cell.get(), Some(val));
38     assert_eq!(cnt.load(SeqCst), 1);
39 }
40 
41 #[test]
once_non_zero_usize_set()42 fn once_non_zero_usize_set() {
43     let val1 = NonZeroUsize::new(92).unwrap();
44     let val2 = NonZeroUsize::new(62).unwrap();
45 
46     let cell = OnceNonZeroUsize::new();
47 
48     assert!(cell.set(val1).is_ok());
49     assert_eq!(cell.get(), Some(val1));
50 
51     assert!(cell.set(val2).is_err());
52     assert_eq!(cell.get(), Some(val1));
53 }
54 
55 #[cfg(feature = "std")]
56 #[test]
once_non_zero_usize_first_wins()57 fn once_non_zero_usize_first_wins() {
58     let val1 = NonZeroUsize::new(92).unwrap();
59     let val2 = NonZeroUsize::new(62).unwrap();
60 
61     let cell = OnceNonZeroUsize::new();
62 
63     let b1 = Barrier::new(2);
64     let b2 = Barrier::new(2);
65     let b3 = Barrier::new(2);
66     scope(|s| {
67         s.spawn(|| {
68             let r1 = cell.get_or_init(|| {
69                 b1.wait();
70                 b2.wait();
71                 val1
72             });
73             assert_eq!(r1, val1);
74             b3.wait();
75         });
76         b1.wait();
77         s.spawn(|| {
78             let r2 = cell.get_or_init(|| {
79                 b2.wait();
80                 b3.wait();
81                 val2
82             });
83             assert_eq!(r2, val1);
84         });
85     });
86 
87     assert_eq!(cell.get(), Some(val1));
88 }
89 
90 #[test]
once_bool_smoke_test()91 fn once_bool_smoke_test() {
92     let cnt = AtomicUsize::new(0);
93     let cell = OnceBool::new();
94     scope(|s| {
95         s.spawn(|| {
96             assert_eq!(
97                 cell.get_or_init(|| {
98                     cnt.fetch_add(1, SeqCst);
99                     false
100                 }),
101                 false
102             );
103             assert_eq!(cnt.load(SeqCst), 1);
104 
105             assert_eq!(
106                 cell.get_or_init(|| {
107                     cnt.fetch_add(1, SeqCst);
108                     false
109                 }),
110                 false
111             );
112             assert_eq!(cnt.load(SeqCst), 1);
113         });
114     });
115     assert_eq!(cell.get(), Some(false));
116     assert_eq!(cnt.load(SeqCst), 1);
117 }
118 
119 #[test]
once_bool_set()120 fn once_bool_set() {
121     let cell = OnceBool::new();
122 
123     assert!(cell.set(false).is_ok());
124     assert_eq!(cell.get(), Some(false));
125 
126     assert!(cell.set(true).is_err());
127     assert_eq!(cell.get(), Some(false));
128 }
129