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] |
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] |
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] |
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] |
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] |
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 | |