1ef40d7f6Sopenharmony_cimod unsync {
2ef40d7f6Sopenharmony_ci    use core::{
3ef40d7f6Sopenharmony_ci        cell::Cell,
4ef40d7f6Sopenharmony_ci        sync::atomic::{AtomicUsize, Ordering::SeqCst},
5ef40d7f6Sopenharmony_ci    };
6ef40d7f6Sopenharmony_ci
7ef40d7f6Sopenharmony_ci    use once_cell::unsync::{Lazy, OnceCell};
8ef40d7f6Sopenharmony_ci
9ef40d7f6Sopenharmony_ci    #[test]
10ef40d7f6Sopenharmony_ci    fn once_cell() {
11ef40d7f6Sopenharmony_ci        let c = OnceCell::new();
12ef40d7f6Sopenharmony_ci        assert!(c.get().is_none());
13ef40d7f6Sopenharmony_ci        c.get_or_init(|| 92);
14ef40d7f6Sopenharmony_ci        assert_eq!(c.get(), Some(&92));
15ef40d7f6Sopenharmony_ci
16ef40d7f6Sopenharmony_ci        c.get_or_init(|| panic!("Kabom!"));
17ef40d7f6Sopenharmony_ci        assert_eq!(c.get(), Some(&92));
18ef40d7f6Sopenharmony_ci    }
19ef40d7f6Sopenharmony_ci
20ef40d7f6Sopenharmony_ci    #[test]
21ef40d7f6Sopenharmony_ci    fn once_cell_with_value() {
22ef40d7f6Sopenharmony_ci        const CELL: OnceCell<i32> = OnceCell::with_value(12);
23ef40d7f6Sopenharmony_ci        let cell = CELL;
24ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(&12));
25ef40d7f6Sopenharmony_ci    }
26ef40d7f6Sopenharmony_ci
27ef40d7f6Sopenharmony_ci    #[test]
28ef40d7f6Sopenharmony_ci    fn once_cell_get_mut() {
29ef40d7f6Sopenharmony_ci        let mut c = OnceCell::new();
30ef40d7f6Sopenharmony_ci        assert!(c.get_mut().is_none());
31ef40d7f6Sopenharmony_ci        c.set(90).unwrap();
32ef40d7f6Sopenharmony_ci        *c.get_mut().unwrap() += 2;
33ef40d7f6Sopenharmony_ci        assert_eq!(c.get_mut(), Some(&mut 92));
34ef40d7f6Sopenharmony_ci    }
35ef40d7f6Sopenharmony_ci
36ef40d7f6Sopenharmony_ci    #[test]
37ef40d7f6Sopenharmony_ci    fn once_cell_drop() {
38ef40d7f6Sopenharmony_ci        static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
39ef40d7f6Sopenharmony_ci        struct Dropper;
40ef40d7f6Sopenharmony_ci        impl Drop for Dropper {
41ef40d7f6Sopenharmony_ci            fn drop(&mut self) {
42ef40d7f6Sopenharmony_ci                DROP_CNT.fetch_add(1, SeqCst);
43ef40d7f6Sopenharmony_ci            }
44ef40d7f6Sopenharmony_ci        }
45ef40d7f6Sopenharmony_ci
46ef40d7f6Sopenharmony_ci        let x = OnceCell::new();
47ef40d7f6Sopenharmony_ci        x.get_or_init(|| Dropper);
48ef40d7f6Sopenharmony_ci        assert_eq!(DROP_CNT.load(SeqCst), 0);
49ef40d7f6Sopenharmony_ci        drop(x);
50ef40d7f6Sopenharmony_ci        assert_eq!(DROP_CNT.load(SeqCst), 1);
51ef40d7f6Sopenharmony_ci    }
52ef40d7f6Sopenharmony_ci
53ef40d7f6Sopenharmony_ci    #[test]
54ef40d7f6Sopenharmony_ci    fn unsync_once_cell_drop_empty() {
55ef40d7f6Sopenharmony_ci        let x = OnceCell::<String>::new();
56ef40d7f6Sopenharmony_ci        drop(x);
57ef40d7f6Sopenharmony_ci    }
58ef40d7f6Sopenharmony_ci
59ef40d7f6Sopenharmony_ci    #[test]
60ef40d7f6Sopenharmony_ci    fn clone() {
61ef40d7f6Sopenharmony_ci        let s = OnceCell::new();
62ef40d7f6Sopenharmony_ci        let c = s.clone();
63ef40d7f6Sopenharmony_ci        assert!(c.get().is_none());
64ef40d7f6Sopenharmony_ci
65ef40d7f6Sopenharmony_ci        s.set("hello".to_string()).unwrap();
66ef40d7f6Sopenharmony_ci        let c = s.clone();
67ef40d7f6Sopenharmony_ci        assert_eq!(c.get().map(String::as_str), Some("hello"));
68ef40d7f6Sopenharmony_ci    }
69ef40d7f6Sopenharmony_ci
70ef40d7f6Sopenharmony_ci    #[test]
71ef40d7f6Sopenharmony_ci    fn from_impl() {
72ef40d7f6Sopenharmony_ci        assert_eq!(OnceCell::from("value").get(), Some(&"value"));
73ef40d7f6Sopenharmony_ci        assert_ne!(OnceCell::from("foo").get(), Some(&"bar"));
74ef40d7f6Sopenharmony_ci    }
75ef40d7f6Sopenharmony_ci
76ef40d7f6Sopenharmony_ci    #[test]
77ef40d7f6Sopenharmony_ci    fn partialeq_impl() {
78ef40d7f6Sopenharmony_ci        assert!(OnceCell::from("value") == OnceCell::from("value"));
79ef40d7f6Sopenharmony_ci        assert!(OnceCell::from("foo") != OnceCell::from("bar"));
80ef40d7f6Sopenharmony_ci
81ef40d7f6Sopenharmony_ci        assert!(OnceCell::<String>::new() == OnceCell::new());
82ef40d7f6Sopenharmony_ci        assert!(OnceCell::<String>::new() != OnceCell::from("value".to_owned()));
83ef40d7f6Sopenharmony_ci    }
84ef40d7f6Sopenharmony_ci
85ef40d7f6Sopenharmony_ci    #[test]
86ef40d7f6Sopenharmony_ci    fn into_inner() {
87ef40d7f6Sopenharmony_ci        let cell: OnceCell<String> = OnceCell::new();
88ef40d7f6Sopenharmony_ci        assert_eq!(cell.into_inner(), None);
89ef40d7f6Sopenharmony_ci        let cell = OnceCell::new();
90ef40d7f6Sopenharmony_ci        cell.set("hello".to_string()).unwrap();
91ef40d7f6Sopenharmony_ci        assert_eq!(cell.into_inner(), Some("hello".to_string()));
92ef40d7f6Sopenharmony_ci    }
93ef40d7f6Sopenharmony_ci
94ef40d7f6Sopenharmony_ci    #[test]
95ef40d7f6Sopenharmony_ci    fn debug_impl() {
96ef40d7f6Sopenharmony_ci        let cell = OnceCell::new();
97ef40d7f6Sopenharmony_ci        assert_eq!(format!("{:?}", cell), "OnceCell(Uninit)");
98ef40d7f6Sopenharmony_ci        cell.set("hello".to_string()).unwrap();
99ef40d7f6Sopenharmony_ci        assert_eq!(format!("{:?}", cell), "OnceCell(\"hello\")");
100ef40d7f6Sopenharmony_ci    }
101ef40d7f6Sopenharmony_ci
102ef40d7f6Sopenharmony_ci    #[test]
103ef40d7f6Sopenharmony_ci    fn lazy_new() {
104ef40d7f6Sopenharmony_ci        let called = Cell::new(0);
105ef40d7f6Sopenharmony_ci        let x = Lazy::new(|| {
106ef40d7f6Sopenharmony_ci            called.set(called.get() + 1);
107ef40d7f6Sopenharmony_ci            92
108ef40d7f6Sopenharmony_ci        });
109ef40d7f6Sopenharmony_ci
110ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 0);
111ef40d7f6Sopenharmony_ci
112ef40d7f6Sopenharmony_ci        let y = *x - 30;
113ef40d7f6Sopenharmony_ci        assert_eq!(y, 62);
114ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 1);
115ef40d7f6Sopenharmony_ci
116ef40d7f6Sopenharmony_ci        let y = *x - 30;
117ef40d7f6Sopenharmony_ci        assert_eq!(y, 62);
118ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 1);
119ef40d7f6Sopenharmony_ci    }
120ef40d7f6Sopenharmony_ci
121ef40d7f6Sopenharmony_ci    #[test]
122ef40d7f6Sopenharmony_ci    fn lazy_deref_mut() {
123ef40d7f6Sopenharmony_ci        let called = Cell::new(0);
124ef40d7f6Sopenharmony_ci        let mut x = Lazy::new(|| {
125ef40d7f6Sopenharmony_ci            called.set(called.get() + 1);
126ef40d7f6Sopenharmony_ci            92
127ef40d7f6Sopenharmony_ci        });
128ef40d7f6Sopenharmony_ci
129ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 0);
130ef40d7f6Sopenharmony_ci
131ef40d7f6Sopenharmony_ci        let y = *x - 30;
132ef40d7f6Sopenharmony_ci        assert_eq!(y, 62);
133ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 1);
134ef40d7f6Sopenharmony_ci
135ef40d7f6Sopenharmony_ci        *x /= 2;
136ef40d7f6Sopenharmony_ci        assert_eq!(*x, 46);
137ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 1);
138ef40d7f6Sopenharmony_ci    }
139ef40d7f6Sopenharmony_ci
140ef40d7f6Sopenharmony_ci    #[test]
141ef40d7f6Sopenharmony_ci    fn lazy_force_mut() {
142ef40d7f6Sopenharmony_ci        let called = Cell::new(0);
143ef40d7f6Sopenharmony_ci        let mut x = Lazy::new(|| {
144ef40d7f6Sopenharmony_ci            called.set(called.get() + 1);
145ef40d7f6Sopenharmony_ci            92
146ef40d7f6Sopenharmony_ci        });
147ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 0);
148ef40d7f6Sopenharmony_ci        let v = Lazy::force_mut(&mut x);
149ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 1);
150ef40d7f6Sopenharmony_ci
151ef40d7f6Sopenharmony_ci        *v /= 2;
152ef40d7f6Sopenharmony_ci        assert_eq!(*x, 46);
153ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 1);
154ef40d7f6Sopenharmony_ci    }
155ef40d7f6Sopenharmony_ci
156ef40d7f6Sopenharmony_ci    #[test]
157ef40d7f6Sopenharmony_ci    fn lazy_get_mut() {
158ef40d7f6Sopenharmony_ci        let called = Cell::new(0);
159ef40d7f6Sopenharmony_ci        let mut x: Lazy<u32, _> = Lazy::new(|| {
160ef40d7f6Sopenharmony_ci            called.set(called.get() + 1);
161ef40d7f6Sopenharmony_ci            92
162ef40d7f6Sopenharmony_ci        });
163ef40d7f6Sopenharmony_ci
164ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 0);
165ef40d7f6Sopenharmony_ci        assert_eq!(*x, 92);
166ef40d7f6Sopenharmony_ci
167ef40d7f6Sopenharmony_ci        let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap();
168ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 1);
169ef40d7f6Sopenharmony_ci
170ef40d7f6Sopenharmony_ci        *mut_ref /= 2;
171ef40d7f6Sopenharmony_ci        assert_eq!(*x, 46);
172ef40d7f6Sopenharmony_ci        assert_eq!(called.get(), 1);
173ef40d7f6Sopenharmony_ci    }
174ef40d7f6Sopenharmony_ci
175ef40d7f6Sopenharmony_ci    #[test]
176ef40d7f6Sopenharmony_ci    fn lazy_default() {
177ef40d7f6Sopenharmony_ci        static CALLED: AtomicUsize = AtomicUsize::new(0);
178ef40d7f6Sopenharmony_ci
179ef40d7f6Sopenharmony_ci        struct Foo(u8);
180ef40d7f6Sopenharmony_ci        impl Default for Foo {
181ef40d7f6Sopenharmony_ci            fn default() -> Self {
182ef40d7f6Sopenharmony_ci                CALLED.fetch_add(1, SeqCst);
183ef40d7f6Sopenharmony_ci                Foo(42)
184ef40d7f6Sopenharmony_ci            }
185ef40d7f6Sopenharmony_ci        }
186ef40d7f6Sopenharmony_ci
187ef40d7f6Sopenharmony_ci        let lazy: Lazy<std::sync::Mutex<Foo>> = <_>::default();
188ef40d7f6Sopenharmony_ci
189ef40d7f6Sopenharmony_ci        assert_eq!(CALLED.load(SeqCst), 0);
190ef40d7f6Sopenharmony_ci
191ef40d7f6Sopenharmony_ci        assert_eq!(lazy.lock().unwrap().0, 42);
192ef40d7f6Sopenharmony_ci        assert_eq!(CALLED.load(SeqCst), 1);
193ef40d7f6Sopenharmony_ci
194ef40d7f6Sopenharmony_ci        lazy.lock().unwrap().0 = 21;
195ef40d7f6Sopenharmony_ci
196ef40d7f6Sopenharmony_ci        assert_eq!(lazy.lock().unwrap().0, 21);
197ef40d7f6Sopenharmony_ci        assert_eq!(CALLED.load(SeqCst), 1);
198ef40d7f6Sopenharmony_ci    }
199ef40d7f6Sopenharmony_ci
200ef40d7f6Sopenharmony_ci    #[test]
201ef40d7f6Sopenharmony_ci    fn lazy_into_value() {
202ef40d7f6Sopenharmony_ci        let l: Lazy<i32, _> = Lazy::new(|| panic!());
203ef40d7f6Sopenharmony_ci        assert!(matches!(Lazy::into_value(l), Err(_)));
204ef40d7f6Sopenharmony_ci        let l = Lazy::new(|| -> i32 { 92 });
205ef40d7f6Sopenharmony_ci        Lazy::force(&l);
206ef40d7f6Sopenharmony_ci        assert!(matches!(Lazy::into_value(l), Ok(92)));
207ef40d7f6Sopenharmony_ci    }
208ef40d7f6Sopenharmony_ci
209ef40d7f6Sopenharmony_ci    #[test]
210ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
211ef40d7f6Sopenharmony_ci    fn lazy_poisoning() {
212ef40d7f6Sopenharmony_ci        let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
213ef40d7f6Sopenharmony_ci        for _ in 0..2 {
214ef40d7f6Sopenharmony_ci            let res = std::panic::catch_unwind(|| x.len());
215ef40d7f6Sopenharmony_ci            assert!(res.is_err());
216ef40d7f6Sopenharmony_ci        }
217ef40d7f6Sopenharmony_ci    }
218ef40d7f6Sopenharmony_ci
219ef40d7f6Sopenharmony_ci    #[test]
220ef40d7f6Sopenharmony_ci    fn aliasing_in_get() {
221ef40d7f6Sopenharmony_ci        let x = OnceCell::new();
222ef40d7f6Sopenharmony_ci        x.set(42).unwrap();
223ef40d7f6Sopenharmony_ci        let at_x = x.get().unwrap(); // --- (shared) borrow of inner `Option<T>` --+
224ef40d7f6Sopenharmony_ci        let _ = x.set(27); // <-- temporary (unique) borrow of inner `Option<T>`   |
225ef40d7f6Sopenharmony_ci        println!("{}", at_x); // <------- up until here ---------------------------+
226ef40d7f6Sopenharmony_ci    }
227ef40d7f6Sopenharmony_ci
228ef40d7f6Sopenharmony_ci    #[test]
229ef40d7f6Sopenharmony_ci    #[should_panic(expected = "reentrant init")]
230ef40d7f6Sopenharmony_ci    fn reentrant_init() {
231ef40d7f6Sopenharmony_ci        let x: OnceCell<Box<i32>> = OnceCell::new();
232ef40d7f6Sopenharmony_ci        let dangling_ref: Cell<Option<&i32>> = Cell::new(None);
233ef40d7f6Sopenharmony_ci        x.get_or_init(|| {
234ef40d7f6Sopenharmony_ci            let r = x.get_or_init(|| Box::new(92));
235ef40d7f6Sopenharmony_ci            dangling_ref.set(Some(r));
236ef40d7f6Sopenharmony_ci            Box::new(62)
237ef40d7f6Sopenharmony_ci        });
238ef40d7f6Sopenharmony_ci        eprintln!("use after free: {:?}", dangling_ref.get().unwrap());
239ef40d7f6Sopenharmony_ci    }
240ef40d7f6Sopenharmony_ci
241ef40d7f6Sopenharmony_ci    #[test]
242ef40d7f6Sopenharmony_ci    // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
243ef40d7f6Sopenharmony_ci    fn arrrrrrrrrrrrrrrrrrrrrr() {
244ef40d7f6Sopenharmony_ci        let cell = OnceCell::new();
245ef40d7f6Sopenharmony_ci        {
246ef40d7f6Sopenharmony_ci            let s = String::new();
247ef40d7f6Sopenharmony_ci            cell.set(&s).unwrap();
248ef40d7f6Sopenharmony_ci        }
249ef40d7f6Sopenharmony_ci    }
250ef40d7f6Sopenharmony_ci}
251ef40d7f6Sopenharmony_ci
252ef40d7f6Sopenharmony_ci#[cfg(any(feature = "std", feature = "critical-section"))]
253ef40d7f6Sopenharmony_cimod sync {
254ef40d7f6Sopenharmony_ci    use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
255ef40d7f6Sopenharmony_ci
256ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
257ef40d7f6Sopenharmony_ci    use std::sync::Barrier;
258ef40d7f6Sopenharmony_ci
259ef40d7f6Sopenharmony_ci    #[cfg(not(feature = "std"))]
260ef40d7f6Sopenharmony_ci    use core::cell::Cell;
261ef40d7f6Sopenharmony_ci
262ef40d7f6Sopenharmony_ci    use crossbeam_utils::thread::scope;
263ef40d7f6Sopenharmony_ci
264ef40d7f6Sopenharmony_ci    use once_cell::sync::{Lazy, OnceCell};
265ef40d7f6Sopenharmony_ci
266ef40d7f6Sopenharmony_ci    #[test]
267ef40d7f6Sopenharmony_ci    fn once_cell() {
268ef40d7f6Sopenharmony_ci        let c = OnceCell::new();
269ef40d7f6Sopenharmony_ci        assert!(c.get().is_none());
270ef40d7f6Sopenharmony_ci        scope(|s| {
271ef40d7f6Sopenharmony_ci            s.spawn(|_| {
272ef40d7f6Sopenharmony_ci                c.get_or_init(|| 92);
273ef40d7f6Sopenharmony_ci                assert_eq!(c.get(), Some(&92));
274ef40d7f6Sopenharmony_ci            });
275ef40d7f6Sopenharmony_ci        })
276ef40d7f6Sopenharmony_ci        .unwrap();
277ef40d7f6Sopenharmony_ci        c.get_or_init(|| panic!("Kabom!"));
278ef40d7f6Sopenharmony_ci        assert_eq!(c.get(), Some(&92));
279ef40d7f6Sopenharmony_ci    }
280ef40d7f6Sopenharmony_ci
281ef40d7f6Sopenharmony_ci    #[test]
282ef40d7f6Sopenharmony_ci    fn once_cell_with_value() {
283ef40d7f6Sopenharmony_ci        static CELL: OnceCell<i32> = OnceCell::with_value(12);
284ef40d7f6Sopenharmony_ci        assert_eq!(CELL.get(), Some(&12));
285ef40d7f6Sopenharmony_ci    }
286ef40d7f6Sopenharmony_ci
287ef40d7f6Sopenharmony_ci    #[test]
288ef40d7f6Sopenharmony_ci    fn once_cell_get_mut() {
289ef40d7f6Sopenharmony_ci        let mut c = OnceCell::new();
290ef40d7f6Sopenharmony_ci        assert!(c.get_mut().is_none());
291ef40d7f6Sopenharmony_ci        c.set(90).unwrap();
292ef40d7f6Sopenharmony_ci        *c.get_mut().unwrap() += 2;
293ef40d7f6Sopenharmony_ci        assert_eq!(c.get_mut(), Some(&mut 92));
294ef40d7f6Sopenharmony_ci    }
295ef40d7f6Sopenharmony_ci
296ef40d7f6Sopenharmony_ci    #[test]
297ef40d7f6Sopenharmony_ci    fn once_cell_get_unchecked() {
298ef40d7f6Sopenharmony_ci        let c = OnceCell::new();
299ef40d7f6Sopenharmony_ci        c.set(92).unwrap();
300ef40d7f6Sopenharmony_ci        unsafe {
301ef40d7f6Sopenharmony_ci            assert_eq!(c.get_unchecked(), &92);
302ef40d7f6Sopenharmony_ci        }
303ef40d7f6Sopenharmony_ci    }
304ef40d7f6Sopenharmony_ci
305ef40d7f6Sopenharmony_ci    #[test]
306ef40d7f6Sopenharmony_ci    fn once_cell_drop() {
307ef40d7f6Sopenharmony_ci        static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
308ef40d7f6Sopenharmony_ci        struct Dropper;
309ef40d7f6Sopenharmony_ci        impl Drop for Dropper {
310ef40d7f6Sopenharmony_ci            fn drop(&mut self) {
311ef40d7f6Sopenharmony_ci                DROP_CNT.fetch_add(1, SeqCst);
312ef40d7f6Sopenharmony_ci            }
313ef40d7f6Sopenharmony_ci        }
314ef40d7f6Sopenharmony_ci
315ef40d7f6Sopenharmony_ci        let x = OnceCell::new();
316ef40d7f6Sopenharmony_ci        scope(|s| {
317ef40d7f6Sopenharmony_ci            s.spawn(|_| {
318ef40d7f6Sopenharmony_ci                x.get_or_init(|| Dropper);
319ef40d7f6Sopenharmony_ci                assert_eq!(DROP_CNT.load(SeqCst), 0);
320ef40d7f6Sopenharmony_ci                drop(x);
321ef40d7f6Sopenharmony_ci            });
322ef40d7f6Sopenharmony_ci        })
323ef40d7f6Sopenharmony_ci        .unwrap();
324ef40d7f6Sopenharmony_ci        assert_eq!(DROP_CNT.load(SeqCst), 1);
325ef40d7f6Sopenharmony_ci    }
326ef40d7f6Sopenharmony_ci
327ef40d7f6Sopenharmony_ci    #[test]
328ef40d7f6Sopenharmony_ci    fn once_cell_drop_empty() {
329ef40d7f6Sopenharmony_ci        let x = OnceCell::<String>::new();
330ef40d7f6Sopenharmony_ci        drop(x);
331ef40d7f6Sopenharmony_ci    }
332ef40d7f6Sopenharmony_ci
333ef40d7f6Sopenharmony_ci    #[test]
334ef40d7f6Sopenharmony_ci    fn clone() {
335ef40d7f6Sopenharmony_ci        let s = OnceCell::new();
336ef40d7f6Sopenharmony_ci        let c = s.clone();
337ef40d7f6Sopenharmony_ci        assert!(c.get().is_none());
338ef40d7f6Sopenharmony_ci
339ef40d7f6Sopenharmony_ci        s.set("hello".to_string()).unwrap();
340ef40d7f6Sopenharmony_ci        let c = s.clone();
341ef40d7f6Sopenharmony_ci        assert_eq!(c.get().map(String::as_str), Some("hello"));
342ef40d7f6Sopenharmony_ci    }
343ef40d7f6Sopenharmony_ci
344ef40d7f6Sopenharmony_ci    #[test]
345ef40d7f6Sopenharmony_ci    fn get_or_try_init() {
346ef40d7f6Sopenharmony_ci        let cell: OnceCell<String> = OnceCell::new();
347ef40d7f6Sopenharmony_ci        assert!(cell.get().is_none());
348ef40d7f6Sopenharmony_ci
349ef40d7f6Sopenharmony_ci        let res =
350ef40d7f6Sopenharmony_ci            std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
351ef40d7f6Sopenharmony_ci        assert!(res.is_err());
352ef40d7f6Sopenharmony_ci        assert!(cell.get().is_none());
353ef40d7f6Sopenharmony_ci
354ef40d7f6Sopenharmony_ci        assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
355ef40d7f6Sopenharmony_ci
356ef40d7f6Sopenharmony_ci        assert_eq!(
357ef40d7f6Sopenharmony_ci            cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())),
358ef40d7f6Sopenharmony_ci            Ok(&"hello".to_string())
359ef40d7f6Sopenharmony_ci        );
360ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(&"hello".to_string()));
361ef40d7f6Sopenharmony_ci    }
362ef40d7f6Sopenharmony_ci
363ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
364ef40d7f6Sopenharmony_ci    #[test]
365ef40d7f6Sopenharmony_ci    fn wait() {
366ef40d7f6Sopenharmony_ci        let cell: OnceCell<String> = OnceCell::new();
367ef40d7f6Sopenharmony_ci        scope(|s| {
368ef40d7f6Sopenharmony_ci            s.spawn(|_| cell.set("hello".to_string()));
369ef40d7f6Sopenharmony_ci            let greeting = cell.wait();
370ef40d7f6Sopenharmony_ci            assert_eq!(greeting, "hello")
371ef40d7f6Sopenharmony_ci        })
372ef40d7f6Sopenharmony_ci        .unwrap();
373ef40d7f6Sopenharmony_ci    }
374ef40d7f6Sopenharmony_ci
375ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
376ef40d7f6Sopenharmony_ci    #[test]
377ef40d7f6Sopenharmony_ci    fn get_or_init_stress() {
378ef40d7f6Sopenharmony_ci        let n_threads = if cfg!(miri) { 30 } else { 1_000 };
379ef40d7f6Sopenharmony_ci        let n_cells = if cfg!(miri) { 30 } else { 1_000 };
380ef40d7f6Sopenharmony_ci        let cells: Vec<_> = std::iter::repeat_with(|| (Barrier::new(n_threads), OnceCell::new()))
381ef40d7f6Sopenharmony_ci            .take(n_cells)
382ef40d7f6Sopenharmony_ci            .collect();
383ef40d7f6Sopenharmony_ci        scope(|s| {
384ef40d7f6Sopenharmony_ci            for t in 0..n_threads {
385ef40d7f6Sopenharmony_ci                let cells = &cells;
386ef40d7f6Sopenharmony_ci                s.spawn(move |_| {
387ef40d7f6Sopenharmony_ci                    for (i, (b, s)) in cells.iter().enumerate() {
388ef40d7f6Sopenharmony_ci                        b.wait();
389ef40d7f6Sopenharmony_ci                        let j = if t % 2 == 0 { s.wait() } else { s.get_or_init(|| i) };
390ef40d7f6Sopenharmony_ci                        assert_eq!(*j, i);
391ef40d7f6Sopenharmony_ci                    }
392ef40d7f6Sopenharmony_ci                });
393ef40d7f6Sopenharmony_ci            }
394ef40d7f6Sopenharmony_ci        })
395ef40d7f6Sopenharmony_ci        .unwrap();
396ef40d7f6Sopenharmony_ci    }
397ef40d7f6Sopenharmony_ci
398ef40d7f6Sopenharmony_ci    #[test]
399ef40d7f6Sopenharmony_ci    fn from_impl() {
400ef40d7f6Sopenharmony_ci        assert_eq!(OnceCell::from("value").get(), Some(&"value"));
401ef40d7f6Sopenharmony_ci        assert_ne!(OnceCell::from("foo").get(), Some(&"bar"));
402ef40d7f6Sopenharmony_ci    }
403ef40d7f6Sopenharmony_ci
404ef40d7f6Sopenharmony_ci    #[test]
405ef40d7f6Sopenharmony_ci    fn partialeq_impl() {
406ef40d7f6Sopenharmony_ci        assert!(OnceCell::from("value") == OnceCell::from("value"));
407ef40d7f6Sopenharmony_ci        assert!(OnceCell::from("foo") != OnceCell::from("bar"));
408ef40d7f6Sopenharmony_ci
409ef40d7f6Sopenharmony_ci        assert!(OnceCell::<String>::new() == OnceCell::new());
410ef40d7f6Sopenharmony_ci        assert!(OnceCell::<String>::new() != OnceCell::from("value".to_owned()));
411ef40d7f6Sopenharmony_ci    }
412ef40d7f6Sopenharmony_ci
413ef40d7f6Sopenharmony_ci    #[test]
414ef40d7f6Sopenharmony_ci    fn into_inner() {
415ef40d7f6Sopenharmony_ci        let cell: OnceCell<String> = OnceCell::new();
416ef40d7f6Sopenharmony_ci        assert_eq!(cell.into_inner(), None);
417ef40d7f6Sopenharmony_ci        let cell = OnceCell::new();
418ef40d7f6Sopenharmony_ci        cell.set("hello".to_string()).unwrap();
419ef40d7f6Sopenharmony_ci        assert_eq!(cell.into_inner(), Some("hello".to_string()));
420ef40d7f6Sopenharmony_ci    }
421ef40d7f6Sopenharmony_ci
422ef40d7f6Sopenharmony_ci    #[test]
423ef40d7f6Sopenharmony_ci    fn debug_impl() {
424ef40d7f6Sopenharmony_ci        let cell = OnceCell::new();
425ef40d7f6Sopenharmony_ci        assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)");
426ef40d7f6Sopenharmony_ci        cell.set(vec!["hello", "world"]).unwrap();
427ef40d7f6Sopenharmony_ci        assert_eq!(
428ef40d7f6Sopenharmony_ci            format!("{:#?}", cell),
429ef40d7f6Sopenharmony_ci            r#"OnceCell(
430ef40d7f6Sopenharmony_ci    [
431ef40d7f6Sopenharmony_ci        "hello",
432ef40d7f6Sopenharmony_ci        "world",
433ef40d7f6Sopenharmony_ci    ],
434ef40d7f6Sopenharmony_ci)"#
435ef40d7f6Sopenharmony_ci        );
436ef40d7f6Sopenharmony_ci    }
437ef40d7f6Sopenharmony_ci
438ef40d7f6Sopenharmony_ci    #[test]
439ef40d7f6Sopenharmony_ci    #[cfg_attr(miri, ignore)] // miri doesn't support processes
440ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
441ef40d7f6Sopenharmony_ci    fn reentrant_init() {
442ef40d7f6Sopenharmony_ci        let examples_dir = {
443ef40d7f6Sopenharmony_ci            let mut exe = std::env::current_exe().unwrap();
444ef40d7f6Sopenharmony_ci            exe.pop();
445ef40d7f6Sopenharmony_ci            exe.pop();
446ef40d7f6Sopenharmony_ci            exe.push("examples");
447ef40d7f6Sopenharmony_ci            exe
448ef40d7f6Sopenharmony_ci        };
449ef40d7f6Sopenharmony_ci        let bin = examples_dir
450ef40d7f6Sopenharmony_ci            .join("reentrant_init_deadlocks")
451ef40d7f6Sopenharmony_ci            .with_extension(std::env::consts::EXE_EXTENSION);
452ef40d7f6Sopenharmony_ci        let mut guard = Guard { child: std::process::Command::new(bin).spawn().unwrap() };
453ef40d7f6Sopenharmony_ci        std::thread::sleep(std::time::Duration::from_secs(2));
454ef40d7f6Sopenharmony_ci        let status = guard.child.try_wait().unwrap();
455ef40d7f6Sopenharmony_ci        assert!(status.is_none());
456ef40d7f6Sopenharmony_ci
457ef40d7f6Sopenharmony_ci        struct Guard {
458ef40d7f6Sopenharmony_ci            child: std::process::Child,
459ef40d7f6Sopenharmony_ci        }
460ef40d7f6Sopenharmony_ci
461ef40d7f6Sopenharmony_ci        impl Drop for Guard {
462ef40d7f6Sopenharmony_ci            fn drop(&mut self) {
463ef40d7f6Sopenharmony_ci                let _ = self.child.kill();
464ef40d7f6Sopenharmony_ci            }
465ef40d7f6Sopenharmony_ci        }
466ef40d7f6Sopenharmony_ci    }
467ef40d7f6Sopenharmony_ci
468ef40d7f6Sopenharmony_ci    #[cfg(not(feature = "std"))]
469ef40d7f6Sopenharmony_ci    #[test]
470ef40d7f6Sopenharmony_ci    #[should_panic(expected = "reentrant init")]
471ef40d7f6Sopenharmony_ci    fn reentrant_init() {
472ef40d7f6Sopenharmony_ci        let x: OnceCell<Box<i32>> = OnceCell::new();
473ef40d7f6Sopenharmony_ci        let dangling_ref: Cell<Option<&i32>> = Cell::new(None);
474ef40d7f6Sopenharmony_ci        x.get_or_init(|| {
475ef40d7f6Sopenharmony_ci            let r = x.get_or_init(|| Box::new(92));
476ef40d7f6Sopenharmony_ci            dangling_ref.set(Some(r));
477ef40d7f6Sopenharmony_ci            Box::new(62)
478ef40d7f6Sopenharmony_ci        });
479ef40d7f6Sopenharmony_ci        eprintln!("use after free: {:?}", dangling_ref.get().unwrap());
480ef40d7f6Sopenharmony_ci    }
481ef40d7f6Sopenharmony_ci
482ef40d7f6Sopenharmony_ci    #[test]
483ef40d7f6Sopenharmony_ci    fn lazy_new() {
484ef40d7f6Sopenharmony_ci        let called = AtomicUsize::new(0);
485ef40d7f6Sopenharmony_ci        let x = Lazy::new(|| {
486ef40d7f6Sopenharmony_ci            called.fetch_add(1, SeqCst);
487ef40d7f6Sopenharmony_ci            92
488ef40d7f6Sopenharmony_ci        });
489ef40d7f6Sopenharmony_ci
490ef40d7f6Sopenharmony_ci        assert_eq!(called.load(SeqCst), 0);
491ef40d7f6Sopenharmony_ci
492ef40d7f6Sopenharmony_ci        scope(|s| {
493ef40d7f6Sopenharmony_ci            s.spawn(|_| {
494ef40d7f6Sopenharmony_ci                let y = *x - 30;
495ef40d7f6Sopenharmony_ci                assert_eq!(y, 62);
496ef40d7f6Sopenharmony_ci                assert_eq!(called.load(SeqCst), 1);
497ef40d7f6Sopenharmony_ci            });
498ef40d7f6Sopenharmony_ci        })
499ef40d7f6Sopenharmony_ci        .unwrap();
500ef40d7f6Sopenharmony_ci
501ef40d7f6Sopenharmony_ci        let y = *x - 30;
502ef40d7f6Sopenharmony_ci        assert_eq!(y, 62);
503ef40d7f6Sopenharmony_ci        assert_eq!(called.load(SeqCst), 1);
504ef40d7f6Sopenharmony_ci    }
505ef40d7f6Sopenharmony_ci
506ef40d7f6Sopenharmony_ci    #[test]
507ef40d7f6Sopenharmony_ci    fn lazy_deref_mut() {
508ef40d7f6Sopenharmony_ci        let called = AtomicUsize::new(0);
509ef40d7f6Sopenharmony_ci        let mut x = Lazy::new(|| {
510ef40d7f6Sopenharmony_ci            called.fetch_add(1, SeqCst);
511ef40d7f6Sopenharmony_ci            92
512ef40d7f6Sopenharmony_ci        });
513ef40d7f6Sopenharmony_ci
514ef40d7f6Sopenharmony_ci        assert_eq!(called.load(SeqCst), 0);
515ef40d7f6Sopenharmony_ci
516ef40d7f6Sopenharmony_ci        let y = *x - 30;
517ef40d7f6Sopenharmony_ci        assert_eq!(y, 62);
518ef40d7f6Sopenharmony_ci        assert_eq!(called.load(SeqCst), 1);
519ef40d7f6Sopenharmony_ci
520ef40d7f6Sopenharmony_ci        *x /= 2;
521ef40d7f6Sopenharmony_ci        assert_eq!(*x, 46);
522ef40d7f6Sopenharmony_ci        assert_eq!(called.load(SeqCst), 1);
523ef40d7f6Sopenharmony_ci    }
524ef40d7f6Sopenharmony_ci
525ef40d7f6Sopenharmony_ci    #[test]
526ef40d7f6Sopenharmony_ci    fn lazy_default() {
527ef40d7f6Sopenharmony_ci        static CALLED: AtomicUsize = AtomicUsize::new(0);
528ef40d7f6Sopenharmony_ci
529ef40d7f6Sopenharmony_ci        struct Foo(u8);
530ef40d7f6Sopenharmony_ci        impl Default for Foo {
531ef40d7f6Sopenharmony_ci            fn default() -> Self {
532ef40d7f6Sopenharmony_ci                CALLED.fetch_add(1, SeqCst);
533ef40d7f6Sopenharmony_ci                Foo(42)
534ef40d7f6Sopenharmony_ci            }
535ef40d7f6Sopenharmony_ci        }
536ef40d7f6Sopenharmony_ci
537ef40d7f6Sopenharmony_ci        let lazy: Lazy<std::sync::Mutex<Foo>> = <_>::default();
538ef40d7f6Sopenharmony_ci
539ef40d7f6Sopenharmony_ci        assert_eq!(CALLED.load(SeqCst), 0);
540ef40d7f6Sopenharmony_ci
541ef40d7f6Sopenharmony_ci        assert_eq!(lazy.lock().unwrap().0, 42);
542ef40d7f6Sopenharmony_ci        assert_eq!(CALLED.load(SeqCst), 1);
543ef40d7f6Sopenharmony_ci
544ef40d7f6Sopenharmony_ci        lazy.lock().unwrap().0 = 21;
545ef40d7f6Sopenharmony_ci
546ef40d7f6Sopenharmony_ci        assert_eq!(lazy.lock().unwrap().0, 21);
547ef40d7f6Sopenharmony_ci        assert_eq!(CALLED.load(SeqCst), 1);
548ef40d7f6Sopenharmony_ci    }
549ef40d7f6Sopenharmony_ci
550ef40d7f6Sopenharmony_ci    #[test]
551ef40d7f6Sopenharmony_ci    fn static_lazy() {
552ef40d7f6Sopenharmony_ci        static XS: Lazy<Vec<i32>> = Lazy::new(|| {
553ef40d7f6Sopenharmony_ci            let mut xs = Vec::new();
554ef40d7f6Sopenharmony_ci            xs.push(1);
555ef40d7f6Sopenharmony_ci            xs.push(2);
556ef40d7f6Sopenharmony_ci            xs.push(3);
557ef40d7f6Sopenharmony_ci            xs
558ef40d7f6Sopenharmony_ci        });
559ef40d7f6Sopenharmony_ci        scope(|s| {
560ef40d7f6Sopenharmony_ci            s.spawn(|_| {
561ef40d7f6Sopenharmony_ci                assert_eq!(&*XS, &vec![1, 2, 3]);
562ef40d7f6Sopenharmony_ci            });
563ef40d7f6Sopenharmony_ci        })
564ef40d7f6Sopenharmony_ci        .unwrap();
565ef40d7f6Sopenharmony_ci        assert_eq!(&*XS, &vec![1, 2, 3]);
566ef40d7f6Sopenharmony_ci    }
567ef40d7f6Sopenharmony_ci
568ef40d7f6Sopenharmony_ci    #[test]
569ef40d7f6Sopenharmony_ci    fn static_lazy_via_fn() {
570ef40d7f6Sopenharmony_ci        fn xs() -> &'static Vec<i32> {
571ef40d7f6Sopenharmony_ci            static XS: OnceCell<Vec<i32>> = OnceCell::new();
572ef40d7f6Sopenharmony_ci            XS.get_or_init(|| {
573ef40d7f6Sopenharmony_ci                let mut xs = Vec::new();
574ef40d7f6Sopenharmony_ci                xs.push(1);
575ef40d7f6Sopenharmony_ci                xs.push(2);
576ef40d7f6Sopenharmony_ci                xs.push(3);
577ef40d7f6Sopenharmony_ci                xs
578ef40d7f6Sopenharmony_ci            })
579ef40d7f6Sopenharmony_ci        }
580ef40d7f6Sopenharmony_ci        assert_eq!(xs(), &vec![1, 2, 3]);
581ef40d7f6Sopenharmony_ci    }
582ef40d7f6Sopenharmony_ci
583ef40d7f6Sopenharmony_ci    #[test]
584ef40d7f6Sopenharmony_ci    fn lazy_into_value() {
585ef40d7f6Sopenharmony_ci        let l: Lazy<i32, _> = Lazy::new(|| panic!());
586ef40d7f6Sopenharmony_ci        assert!(matches!(Lazy::into_value(l), Err(_)));
587ef40d7f6Sopenharmony_ci        let l = Lazy::new(|| -> i32 { 92 });
588ef40d7f6Sopenharmony_ci        Lazy::force(&l);
589ef40d7f6Sopenharmony_ci        assert!(matches!(Lazy::into_value(l), Ok(92)));
590ef40d7f6Sopenharmony_ci    }
591ef40d7f6Sopenharmony_ci
592ef40d7f6Sopenharmony_ci    #[test]
593ef40d7f6Sopenharmony_ci    fn lazy_poisoning() {
594ef40d7f6Sopenharmony_ci        let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
595ef40d7f6Sopenharmony_ci        for _ in 0..2 {
596ef40d7f6Sopenharmony_ci            let res = std::panic::catch_unwind(|| x.len());
597ef40d7f6Sopenharmony_ci            assert!(res.is_err());
598ef40d7f6Sopenharmony_ci        }
599ef40d7f6Sopenharmony_ci    }
600ef40d7f6Sopenharmony_ci
601ef40d7f6Sopenharmony_ci    #[test]
602ef40d7f6Sopenharmony_ci    fn once_cell_is_sync_send() {
603ef40d7f6Sopenharmony_ci        fn assert_traits<T: Send + Sync>() {}
604ef40d7f6Sopenharmony_ci        assert_traits::<OnceCell<String>>();
605ef40d7f6Sopenharmony_ci        assert_traits::<Lazy<String>>();
606ef40d7f6Sopenharmony_ci    }
607ef40d7f6Sopenharmony_ci
608ef40d7f6Sopenharmony_ci    #[test]
609ef40d7f6Sopenharmony_ci    fn eval_once_macro() {
610ef40d7f6Sopenharmony_ci        macro_rules! eval_once {
611ef40d7f6Sopenharmony_ci            (|| -> $ty:ty {
612ef40d7f6Sopenharmony_ci                $($body:tt)*
613ef40d7f6Sopenharmony_ci            }) => {{
614ef40d7f6Sopenharmony_ci                static ONCE_CELL: OnceCell<$ty> = OnceCell::new();
615ef40d7f6Sopenharmony_ci                fn init() -> $ty {
616ef40d7f6Sopenharmony_ci                    $($body)*
617ef40d7f6Sopenharmony_ci                }
618ef40d7f6Sopenharmony_ci                ONCE_CELL.get_or_init(init)
619ef40d7f6Sopenharmony_ci            }};
620ef40d7f6Sopenharmony_ci        }
621ef40d7f6Sopenharmony_ci
622ef40d7f6Sopenharmony_ci        let fib: &'static Vec<i32> = eval_once! {
623ef40d7f6Sopenharmony_ci            || -> Vec<i32> {
624ef40d7f6Sopenharmony_ci                let mut res = vec![1, 1];
625ef40d7f6Sopenharmony_ci                for i in 0..10 {
626ef40d7f6Sopenharmony_ci                    let next = res[i] + res[i + 1];
627ef40d7f6Sopenharmony_ci                    res.push(next);
628ef40d7f6Sopenharmony_ci                }
629ef40d7f6Sopenharmony_ci                res
630ef40d7f6Sopenharmony_ci            }
631ef40d7f6Sopenharmony_ci        };
632ef40d7f6Sopenharmony_ci        assert_eq!(fib[5], 8)
633ef40d7f6Sopenharmony_ci    }
634ef40d7f6Sopenharmony_ci
635ef40d7f6Sopenharmony_ci    #[test]
636ef40d7f6Sopenharmony_ci    fn once_cell_does_not_leak_partially_constructed_boxes() {
637ef40d7f6Sopenharmony_ci        let n_tries = if cfg!(miri) { 10 } else { 100 };
638ef40d7f6Sopenharmony_ci        let n_readers = 10;
639ef40d7f6Sopenharmony_ci        let n_writers = 3;
640ef40d7f6Sopenharmony_ci        const MSG: &str = "Hello, World";
641ef40d7f6Sopenharmony_ci
642ef40d7f6Sopenharmony_ci        for _ in 0..n_tries {
643ef40d7f6Sopenharmony_ci            let cell: OnceCell<String> = OnceCell::new();
644ef40d7f6Sopenharmony_ci            scope(|scope| {
645ef40d7f6Sopenharmony_ci                for _ in 0..n_readers {
646ef40d7f6Sopenharmony_ci                    scope.spawn(|_| loop {
647ef40d7f6Sopenharmony_ci                        if let Some(msg) = cell.get() {
648ef40d7f6Sopenharmony_ci                            assert_eq!(msg, MSG);
649ef40d7f6Sopenharmony_ci                            break;
650ef40d7f6Sopenharmony_ci                        }
651ef40d7f6Sopenharmony_ci                    });
652ef40d7f6Sopenharmony_ci                }
653ef40d7f6Sopenharmony_ci                for _ in 0..n_writers {
654ef40d7f6Sopenharmony_ci                    let _ = scope.spawn(|_| cell.set(MSG.to_owned()));
655ef40d7f6Sopenharmony_ci                }
656ef40d7f6Sopenharmony_ci            })
657ef40d7f6Sopenharmony_ci            .unwrap()
658ef40d7f6Sopenharmony_ci        }
659ef40d7f6Sopenharmony_ci    }
660ef40d7f6Sopenharmony_ci
661ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
662ef40d7f6Sopenharmony_ci    #[test]
663ef40d7f6Sopenharmony_ci    fn get_does_not_block() {
664ef40d7f6Sopenharmony_ci        let cell = OnceCell::new();
665ef40d7f6Sopenharmony_ci        let barrier = Barrier::new(2);
666ef40d7f6Sopenharmony_ci        scope(|scope| {
667ef40d7f6Sopenharmony_ci            scope.spawn(|_| {
668ef40d7f6Sopenharmony_ci                cell.get_or_init(|| {
669ef40d7f6Sopenharmony_ci                    barrier.wait();
670ef40d7f6Sopenharmony_ci                    barrier.wait();
671ef40d7f6Sopenharmony_ci                    "hello".to_string()
672ef40d7f6Sopenharmony_ci                });
673ef40d7f6Sopenharmony_ci            });
674ef40d7f6Sopenharmony_ci            barrier.wait();
675ef40d7f6Sopenharmony_ci            assert_eq!(cell.get(), None);
676ef40d7f6Sopenharmony_ci            barrier.wait();
677ef40d7f6Sopenharmony_ci        })
678ef40d7f6Sopenharmony_ci        .unwrap();
679ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(&"hello".to_string()));
680ef40d7f6Sopenharmony_ci    }
681ef40d7f6Sopenharmony_ci
682ef40d7f6Sopenharmony_ci    #[test]
683ef40d7f6Sopenharmony_ci    // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
684ef40d7f6Sopenharmony_ci    fn arrrrrrrrrrrrrrrrrrrrrr() {
685ef40d7f6Sopenharmony_ci        let cell = OnceCell::new();
686ef40d7f6Sopenharmony_ci        {
687ef40d7f6Sopenharmony_ci            let s = String::new();
688ef40d7f6Sopenharmony_ci            cell.set(&s).unwrap();
689ef40d7f6Sopenharmony_ci        }
690ef40d7f6Sopenharmony_ci    }
691ef40d7f6Sopenharmony_ci}
692ef40d7f6Sopenharmony_ci
693ef40d7f6Sopenharmony_ci#[cfg(feature = "race")]
694ef40d7f6Sopenharmony_cimod race {
695ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
696ef40d7f6Sopenharmony_ci    use std::sync::Barrier;
697ef40d7f6Sopenharmony_ci    use std::{
698ef40d7f6Sopenharmony_ci        num::NonZeroUsize,
699ef40d7f6Sopenharmony_ci        sync::atomic::{AtomicUsize, Ordering::SeqCst},
700ef40d7f6Sopenharmony_ci    };
701ef40d7f6Sopenharmony_ci
702ef40d7f6Sopenharmony_ci    use crossbeam_utils::thread::scope;
703ef40d7f6Sopenharmony_ci
704ef40d7f6Sopenharmony_ci    use once_cell::race::{OnceBool, OnceNonZeroUsize};
705ef40d7f6Sopenharmony_ci
706ef40d7f6Sopenharmony_ci    #[test]
707ef40d7f6Sopenharmony_ci    fn once_non_zero_usize_smoke_test() {
708ef40d7f6Sopenharmony_ci        let cnt = AtomicUsize::new(0);
709ef40d7f6Sopenharmony_ci        let cell = OnceNonZeroUsize::new();
710ef40d7f6Sopenharmony_ci        let val = NonZeroUsize::new(92).unwrap();
711ef40d7f6Sopenharmony_ci        scope(|s| {
712ef40d7f6Sopenharmony_ci            s.spawn(|_| {
713ef40d7f6Sopenharmony_ci                assert_eq!(
714ef40d7f6Sopenharmony_ci                    cell.get_or_init(|| {
715ef40d7f6Sopenharmony_ci                        cnt.fetch_add(1, SeqCst);
716ef40d7f6Sopenharmony_ci                        val
717ef40d7f6Sopenharmony_ci                    }),
718ef40d7f6Sopenharmony_ci                    val
719ef40d7f6Sopenharmony_ci                );
720ef40d7f6Sopenharmony_ci                assert_eq!(cnt.load(SeqCst), 1);
721ef40d7f6Sopenharmony_ci
722ef40d7f6Sopenharmony_ci                assert_eq!(
723ef40d7f6Sopenharmony_ci                    cell.get_or_init(|| {
724ef40d7f6Sopenharmony_ci                        cnt.fetch_add(1, SeqCst);
725ef40d7f6Sopenharmony_ci                        val
726ef40d7f6Sopenharmony_ci                    }),
727ef40d7f6Sopenharmony_ci                    val
728ef40d7f6Sopenharmony_ci                );
729ef40d7f6Sopenharmony_ci                assert_eq!(cnt.load(SeqCst), 1);
730ef40d7f6Sopenharmony_ci            });
731ef40d7f6Sopenharmony_ci        })
732ef40d7f6Sopenharmony_ci        .unwrap();
733ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(val));
734ef40d7f6Sopenharmony_ci        assert_eq!(cnt.load(SeqCst), 1);
735ef40d7f6Sopenharmony_ci    }
736ef40d7f6Sopenharmony_ci
737ef40d7f6Sopenharmony_ci    #[test]
738ef40d7f6Sopenharmony_ci    fn once_non_zero_usize_set() {
739ef40d7f6Sopenharmony_ci        let val1 = NonZeroUsize::new(92).unwrap();
740ef40d7f6Sopenharmony_ci        let val2 = NonZeroUsize::new(62).unwrap();
741ef40d7f6Sopenharmony_ci
742ef40d7f6Sopenharmony_ci        let cell = OnceNonZeroUsize::new();
743ef40d7f6Sopenharmony_ci
744ef40d7f6Sopenharmony_ci        assert!(cell.set(val1).is_ok());
745ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(val1));
746ef40d7f6Sopenharmony_ci
747ef40d7f6Sopenharmony_ci        assert!(cell.set(val2).is_err());
748ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(val1));
749ef40d7f6Sopenharmony_ci    }
750ef40d7f6Sopenharmony_ci
751ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
752ef40d7f6Sopenharmony_ci    #[test]
753ef40d7f6Sopenharmony_ci    fn once_non_zero_usize_first_wins() {
754ef40d7f6Sopenharmony_ci        let val1 = NonZeroUsize::new(92).unwrap();
755ef40d7f6Sopenharmony_ci        let val2 = NonZeroUsize::new(62).unwrap();
756ef40d7f6Sopenharmony_ci
757ef40d7f6Sopenharmony_ci        let cell = OnceNonZeroUsize::new();
758ef40d7f6Sopenharmony_ci
759ef40d7f6Sopenharmony_ci        let b1 = Barrier::new(2);
760ef40d7f6Sopenharmony_ci        let b2 = Barrier::new(2);
761ef40d7f6Sopenharmony_ci        let b3 = Barrier::new(2);
762ef40d7f6Sopenharmony_ci        scope(|s| {
763ef40d7f6Sopenharmony_ci            s.spawn(|_| {
764ef40d7f6Sopenharmony_ci                let r1 = cell.get_or_init(|| {
765ef40d7f6Sopenharmony_ci                    b1.wait();
766ef40d7f6Sopenharmony_ci                    b2.wait();
767ef40d7f6Sopenharmony_ci                    val1
768ef40d7f6Sopenharmony_ci                });
769ef40d7f6Sopenharmony_ci                assert_eq!(r1, val1);
770ef40d7f6Sopenharmony_ci                b3.wait();
771ef40d7f6Sopenharmony_ci            });
772ef40d7f6Sopenharmony_ci            b1.wait();
773ef40d7f6Sopenharmony_ci            s.spawn(|_| {
774ef40d7f6Sopenharmony_ci                let r2 = cell.get_or_init(|| {
775ef40d7f6Sopenharmony_ci                    b2.wait();
776ef40d7f6Sopenharmony_ci                    b3.wait();
777ef40d7f6Sopenharmony_ci                    val2
778ef40d7f6Sopenharmony_ci                });
779ef40d7f6Sopenharmony_ci                assert_eq!(r2, val1);
780ef40d7f6Sopenharmony_ci            });
781ef40d7f6Sopenharmony_ci        })
782ef40d7f6Sopenharmony_ci        .unwrap();
783ef40d7f6Sopenharmony_ci
784ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(val1));
785ef40d7f6Sopenharmony_ci    }
786ef40d7f6Sopenharmony_ci
787ef40d7f6Sopenharmony_ci    #[test]
788ef40d7f6Sopenharmony_ci    fn once_bool_smoke_test() {
789ef40d7f6Sopenharmony_ci        let cnt = AtomicUsize::new(0);
790ef40d7f6Sopenharmony_ci        let cell = OnceBool::new();
791ef40d7f6Sopenharmony_ci        scope(|s| {
792ef40d7f6Sopenharmony_ci            s.spawn(|_| {
793ef40d7f6Sopenharmony_ci                assert_eq!(
794ef40d7f6Sopenharmony_ci                    cell.get_or_init(|| {
795ef40d7f6Sopenharmony_ci                        cnt.fetch_add(1, SeqCst);
796ef40d7f6Sopenharmony_ci                        false
797ef40d7f6Sopenharmony_ci                    }),
798ef40d7f6Sopenharmony_ci                    false
799ef40d7f6Sopenharmony_ci                );
800ef40d7f6Sopenharmony_ci                assert_eq!(cnt.load(SeqCst), 1);
801ef40d7f6Sopenharmony_ci
802ef40d7f6Sopenharmony_ci                assert_eq!(
803ef40d7f6Sopenharmony_ci                    cell.get_or_init(|| {
804ef40d7f6Sopenharmony_ci                        cnt.fetch_add(1, SeqCst);
805ef40d7f6Sopenharmony_ci                        false
806ef40d7f6Sopenharmony_ci                    }),
807ef40d7f6Sopenharmony_ci                    false
808ef40d7f6Sopenharmony_ci                );
809ef40d7f6Sopenharmony_ci                assert_eq!(cnt.load(SeqCst), 1);
810ef40d7f6Sopenharmony_ci            });
811ef40d7f6Sopenharmony_ci        })
812ef40d7f6Sopenharmony_ci        .unwrap();
813ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(false));
814ef40d7f6Sopenharmony_ci        assert_eq!(cnt.load(SeqCst), 1);
815ef40d7f6Sopenharmony_ci    }
816ef40d7f6Sopenharmony_ci
817ef40d7f6Sopenharmony_ci    #[test]
818ef40d7f6Sopenharmony_ci    fn once_bool_set() {
819ef40d7f6Sopenharmony_ci        let cell = OnceBool::new();
820ef40d7f6Sopenharmony_ci
821ef40d7f6Sopenharmony_ci        assert!(cell.set(false).is_ok());
822ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(false));
823ef40d7f6Sopenharmony_ci
824ef40d7f6Sopenharmony_ci        assert!(cell.set(true).is_err());
825ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(false));
826ef40d7f6Sopenharmony_ci    }
827ef40d7f6Sopenharmony_ci}
828ef40d7f6Sopenharmony_ci
829ef40d7f6Sopenharmony_ci#[cfg(all(feature = "race", feature = "alloc"))]
830ef40d7f6Sopenharmony_cimod race_once_box {
831ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
832ef40d7f6Sopenharmony_ci    use std::sync::Barrier;
833ef40d7f6Sopenharmony_ci    use std::sync::{
834ef40d7f6Sopenharmony_ci        atomic::{AtomicUsize, Ordering::SeqCst},
835ef40d7f6Sopenharmony_ci        Arc,
836ef40d7f6Sopenharmony_ci    };
837ef40d7f6Sopenharmony_ci
838ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
839ef40d7f6Sopenharmony_ci    use crossbeam_utils::thread::scope;
840ef40d7f6Sopenharmony_ci
841ef40d7f6Sopenharmony_ci    use once_cell::race::OnceBox;
842ef40d7f6Sopenharmony_ci
843ef40d7f6Sopenharmony_ci    #[derive(Default)]
844ef40d7f6Sopenharmony_ci    struct Heap {
845ef40d7f6Sopenharmony_ci        total: Arc<AtomicUsize>,
846ef40d7f6Sopenharmony_ci    }
847ef40d7f6Sopenharmony_ci
848ef40d7f6Sopenharmony_ci    #[derive(Debug)]
849ef40d7f6Sopenharmony_ci    struct Pebble<T> {
850ef40d7f6Sopenharmony_ci        val: T,
851ef40d7f6Sopenharmony_ci        total: Arc<AtomicUsize>,
852ef40d7f6Sopenharmony_ci    }
853ef40d7f6Sopenharmony_ci
854ef40d7f6Sopenharmony_ci    impl<T> Drop for Pebble<T> {
855ef40d7f6Sopenharmony_ci        fn drop(&mut self) {
856ef40d7f6Sopenharmony_ci            self.total.fetch_sub(1, SeqCst);
857ef40d7f6Sopenharmony_ci        }
858ef40d7f6Sopenharmony_ci    }
859ef40d7f6Sopenharmony_ci
860ef40d7f6Sopenharmony_ci    impl Heap {
861ef40d7f6Sopenharmony_ci        fn total(&self) -> usize {
862ef40d7f6Sopenharmony_ci            self.total.load(SeqCst)
863ef40d7f6Sopenharmony_ci        }
864ef40d7f6Sopenharmony_ci        fn new_pebble<T>(&self, val: T) -> Pebble<T> {
865ef40d7f6Sopenharmony_ci            self.total.fetch_add(1, SeqCst);
866ef40d7f6Sopenharmony_ci            Pebble { val, total: Arc::clone(&self.total) }
867ef40d7f6Sopenharmony_ci        }
868ef40d7f6Sopenharmony_ci    }
869ef40d7f6Sopenharmony_ci
870ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
871ef40d7f6Sopenharmony_ci    #[test]
872ef40d7f6Sopenharmony_ci    fn once_box_smoke_test() {
873ef40d7f6Sopenharmony_ci        let heap = Heap::default();
874ef40d7f6Sopenharmony_ci        let global_cnt = AtomicUsize::new(0);
875ef40d7f6Sopenharmony_ci        let cell = OnceBox::new();
876ef40d7f6Sopenharmony_ci        let b = Barrier::new(128);
877ef40d7f6Sopenharmony_ci        scope(|s| {
878ef40d7f6Sopenharmony_ci            for _ in 0..128 {
879ef40d7f6Sopenharmony_ci                s.spawn(|_| {
880ef40d7f6Sopenharmony_ci                    let local_cnt = AtomicUsize::new(0);
881ef40d7f6Sopenharmony_ci                    cell.get_or_init(|| {
882ef40d7f6Sopenharmony_ci                        global_cnt.fetch_add(1, SeqCst);
883ef40d7f6Sopenharmony_ci                        local_cnt.fetch_add(1, SeqCst);
884ef40d7f6Sopenharmony_ci                        b.wait();
885ef40d7f6Sopenharmony_ci                        Box::new(heap.new_pebble(()))
886ef40d7f6Sopenharmony_ci                    });
887ef40d7f6Sopenharmony_ci                    assert_eq!(local_cnt.load(SeqCst), 1);
888ef40d7f6Sopenharmony_ci
889ef40d7f6Sopenharmony_ci                    cell.get_or_init(|| {
890ef40d7f6Sopenharmony_ci                        global_cnt.fetch_add(1, SeqCst);
891ef40d7f6Sopenharmony_ci                        local_cnt.fetch_add(1, SeqCst);
892ef40d7f6Sopenharmony_ci                        Box::new(heap.new_pebble(()))
893ef40d7f6Sopenharmony_ci                    });
894ef40d7f6Sopenharmony_ci                    assert_eq!(local_cnt.load(SeqCst), 1);
895ef40d7f6Sopenharmony_ci                });
896ef40d7f6Sopenharmony_ci            }
897ef40d7f6Sopenharmony_ci        })
898ef40d7f6Sopenharmony_ci        .unwrap();
899ef40d7f6Sopenharmony_ci        assert!(cell.get().is_some());
900ef40d7f6Sopenharmony_ci        assert!(global_cnt.load(SeqCst) > 10);
901ef40d7f6Sopenharmony_ci
902ef40d7f6Sopenharmony_ci        assert_eq!(heap.total(), 1);
903ef40d7f6Sopenharmony_ci        drop(cell);
904ef40d7f6Sopenharmony_ci        assert_eq!(heap.total(), 0);
905ef40d7f6Sopenharmony_ci    }
906ef40d7f6Sopenharmony_ci
907ef40d7f6Sopenharmony_ci    #[test]
908ef40d7f6Sopenharmony_ci    fn once_box_set() {
909ef40d7f6Sopenharmony_ci        let heap = Heap::default();
910ef40d7f6Sopenharmony_ci        let cell = OnceBox::new();
911ef40d7f6Sopenharmony_ci        assert!(cell.get().is_none());
912ef40d7f6Sopenharmony_ci
913ef40d7f6Sopenharmony_ci        assert!(cell.set(Box::new(heap.new_pebble("hello"))).is_ok());
914ef40d7f6Sopenharmony_ci        assert_eq!(cell.get().unwrap().val, "hello");
915ef40d7f6Sopenharmony_ci        assert_eq!(heap.total(), 1);
916ef40d7f6Sopenharmony_ci
917ef40d7f6Sopenharmony_ci        assert!(cell.set(Box::new(heap.new_pebble("world"))).is_err());
918ef40d7f6Sopenharmony_ci        assert_eq!(cell.get().unwrap().val, "hello");
919ef40d7f6Sopenharmony_ci        assert_eq!(heap.total(), 1);
920ef40d7f6Sopenharmony_ci
921ef40d7f6Sopenharmony_ci        drop(cell);
922ef40d7f6Sopenharmony_ci        assert_eq!(heap.total(), 0);
923ef40d7f6Sopenharmony_ci    }
924ef40d7f6Sopenharmony_ci
925ef40d7f6Sopenharmony_ci    #[cfg(feature = "std")]
926ef40d7f6Sopenharmony_ci    #[test]
927ef40d7f6Sopenharmony_ci    fn once_box_first_wins() {
928ef40d7f6Sopenharmony_ci        let cell = OnceBox::new();
929ef40d7f6Sopenharmony_ci        let val1 = 92;
930ef40d7f6Sopenharmony_ci        let val2 = 62;
931ef40d7f6Sopenharmony_ci
932ef40d7f6Sopenharmony_ci        let b1 = Barrier::new(2);
933ef40d7f6Sopenharmony_ci        let b2 = Barrier::new(2);
934ef40d7f6Sopenharmony_ci        let b3 = Barrier::new(2);
935ef40d7f6Sopenharmony_ci        scope(|s| {
936ef40d7f6Sopenharmony_ci            s.spawn(|_| {
937ef40d7f6Sopenharmony_ci                let r1 = cell.get_or_init(|| {
938ef40d7f6Sopenharmony_ci                    b1.wait();
939ef40d7f6Sopenharmony_ci                    b2.wait();
940ef40d7f6Sopenharmony_ci                    Box::new(val1)
941ef40d7f6Sopenharmony_ci                });
942ef40d7f6Sopenharmony_ci                assert_eq!(*r1, val1);
943ef40d7f6Sopenharmony_ci                b3.wait();
944ef40d7f6Sopenharmony_ci            });
945ef40d7f6Sopenharmony_ci            b1.wait();
946ef40d7f6Sopenharmony_ci            s.spawn(|_| {
947ef40d7f6Sopenharmony_ci                let r2 = cell.get_or_init(|| {
948ef40d7f6Sopenharmony_ci                    b2.wait();
949ef40d7f6Sopenharmony_ci                    b3.wait();
950ef40d7f6Sopenharmony_ci                    Box::new(val2)
951ef40d7f6Sopenharmony_ci                });
952ef40d7f6Sopenharmony_ci                assert_eq!(*r2, val1);
953ef40d7f6Sopenharmony_ci            });
954ef40d7f6Sopenharmony_ci        })
955ef40d7f6Sopenharmony_ci        .unwrap();
956ef40d7f6Sopenharmony_ci
957ef40d7f6Sopenharmony_ci        assert_eq!(cell.get(), Some(&val1));
958ef40d7f6Sopenharmony_ci    }
959ef40d7f6Sopenharmony_ci
960ef40d7f6Sopenharmony_ci    #[test]
961ef40d7f6Sopenharmony_ci    fn once_box_reentrant() {
962ef40d7f6Sopenharmony_ci        let cell = OnceBox::new();
963ef40d7f6Sopenharmony_ci        let res = cell.get_or_init(|| {
964ef40d7f6Sopenharmony_ci            cell.get_or_init(|| Box::new("hello".to_string()));
965ef40d7f6Sopenharmony_ci            Box::new("world".to_string())
966ef40d7f6Sopenharmony_ci        });
967ef40d7f6Sopenharmony_ci        assert_eq!(res, "hello");
968ef40d7f6Sopenharmony_ci    }
969ef40d7f6Sopenharmony_ci
970ef40d7f6Sopenharmony_ci    #[test]
971ef40d7f6Sopenharmony_ci    fn once_box_default() {
972ef40d7f6Sopenharmony_ci        struct Foo;
973ef40d7f6Sopenharmony_ci
974ef40d7f6Sopenharmony_ci        let cell: OnceBox<Foo> = Default::default();
975ef40d7f6Sopenharmony_ci        assert!(cell.get().is_none());
976ef40d7f6Sopenharmony_ci    }
977ef40d7f6Sopenharmony_ci}
978