1#[cfg(feature = "std")]
2use std::sync::Barrier;
3use std::{
4 num::NonZeroUsize,
5 sync::atomic::{AtomicUsize, Ordering::SeqCst},
6 thread::scope,
7};
8
9use once_cell::race::{OnceBool, OnceNonZeroUsize};
10
11#[test]
12fn 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]
42fn 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]
57fn 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]
91fn 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]
120fn 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