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