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