2 lazy
::{Lazy, SyncLazy, SyncOnceCell}
,
5 atomic
::{AtomicUsize, Ordering::SeqCst}
,
14 static CALLED
: AtomicUsize
= AtomicUsize
::new(0);
17 impl Default
for Foo
{
18 fn default() -> Self {
19 CALLED
.fetch_add(1, SeqCst
);
24 let lazy
: Lazy
<Mutex
<Foo
>> = <_
>::default();
26 assert_eq
!(CALLED
.load(SeqCst
), 0);
28 assert_eq
!(lazy
.lock().unwrap().0, 42);
29 assert_eq
!(CALLED
.load(SeqCst
), 1);
31 lazy
.lock().unwrap().0 = 21;
33 assert_eq
!(lazy
.lock().unwrap().0, 21);
34 assert_eq
!(CALLED
.load(SeqCst
), 1);
39 let x
: Lazy
<String
> = Lazy
::new(|| panic
!("kaboom"));
41 let res
= panic
::catch_unwind(panic
::AssertUnwindSafe(|| x
.len()));
42 assert
!(res
.is_err());
46 fn spawn_and_wait
<R
: Send
+ '
static>(f
: impl FnOnce() -> R
+ Send
+ '
static) -> R
{
47 thread
::spawn(f
).join().unwrap()
52 static ONCE_CELL
: SyncOnceCell
<i32> = SyncOnceCell
::new();
54 assert
!(ONCE_CELL
.get().is_none());
57 ONCE_CELL
.get_or_init(|| 92);
58 assert_eq
!(ONCE_CELL
.get(), Some(&92));
61 ONCE_CELL
.get_or_init(|| panic
!("Kabom!"));
62 assert_eq
!(ONCE_CELL
.get(), Some(&92));
66 fn sync_once_cell_get_mut() {
67 let mut c
= SyncOnceCell
::new();
68 assert
!(c
.get_mut().is_none());
70 *c
.get_mut().unwrap() += 2;
71 assert_eq
!(c
.get_mut(), Some(&mut 92));
75 fn sync_once_cell_get_unchecked() {
76 let c
= SyncOnceCell
::new();
79 assert_eq
!(c
.get_unchecked(), &92);
84 fn sync_once_cell_drop() {
85 static DROP_CNT
: AtomicUsize
= AtomicUsize
::new(0);
87 impl Drop
for Dropper
{
89 DROP_CNT
.fetch_add(1, SeqCst
);
93 let x
= SyncOnceCell
::new();
94 spawn_and_wait(move || {
95 x
.get_or_init(|| Dropper
);
96 assert_eq
!(DROP_CNT
.load(SeqCst
), 0);
100 assert_eq
!(DROP_CNT
.load(SeqCst
), 1);
104 fn sync_once_cell_drop_empty() {
105 let x
= SyncOnceCell
::<String
>::new();
111 let s
= SyncOnceCell
::new();
113 assert
!(c
.get().is_none());
115 s
.set("hello".to_string()).unwrap();
117 assert_eq
!(c
.get().map(String
::as_str
), Some("hello"));
121 fn get_or_try_init() {
122 let cell
: SyncOnceCell
<String
> = SyncOnceCell
::new();
123 assert
!(cell
.get().is_none());
125 let res
= panic
::catch_unwind(|| cell
.get_or_try_init(|| -> Result
<_
, ()> { panic!() }
));
126 assert
!(res
.is_err());
127 assert
!(!cell
.is_initialized());
128 assert
!(cell
.get().is_none());
130 assert_eq
!(cell
.get_or_try_init(|| Err(())), Err(()));
132 assert_eq
!(cell
.get_or_try_init(|| Ok
::<_
, ()>("hello".to_string())), Ok(&"hello".to_string()));
133 assert_eq
!(cell
.get(), Some(&"hello".to_string()));
138 assert_eq
!(SyncOnceCell
::from("value").get(), Some(&"value"));
139 assert_ne
!(SyncOnceCell
::from("foo").get(), Some(&"bar"));
143 fn partialeq_impl() {
144 assert
!(SyncOnceCell
::from("value") == SyncOnceCell
::from("value"));
145 assert
!(SyncOnceCell
::from("foo") != SyncOnceCell
::from("bar"));
147 assert
!(SyncOnceCell
::<String
>::new() == SyncOnceCell
::new());
148 assert
!(SyncOnceCell
::<String
>::new() != SyncOnceCell
::from("value".to_owned()));
153 let cell
: SyncOnceCell
<String
> = SyncOnceCell
::new();
154 assert_eq
!(cell
.into_inner(), None
);
155 let cell
= SyncOnceCell
::new();
156 cell
.set("hello".to_string()).unwrap();
157 assert_eq
!(cell
.into_inner(), Some("hello".to_string()));
162 static CALLED
: AtomicUsize
= AtomicUsize
::new(0);
163 static SYNC_LAZY
: SyncLazy
<i32> = SyncLazy
::new(|| {
164 CALLED
.fetch_add(1, SeqCst
);
168 assert_eq
!(CALLED
.load(SeqCst
), 0);
171 let y
= *SYNC_LAZY
- 30;
173 assert_eq
!(CALLED
.load(SeqCst
), 1);
176 let y
= *SYNC_LAZY
- 30;
178 assert_eq
!(CALLED
.load(SeqCst
), 1);
182 fn sync_lazy_default() {
183 static CALLED
: AtomicUsize
= AtomicUsize
::new(0);
186 impl Default
for Foo
{
187 fn default() -> Self {
188 CALLED
.fetch_add(1, SeqCst
);
193 let lazy
: SyncLazy
<Mutex
<Foo
>> = <_
>::default();
195 assert_eq
!(CALLED
.load(SeqCst
), 0);
197 assert_eq
!(lazy
.lock().unwrap().0, 42);
198 assert_eq
!(CALLED
.load(SeqCst
), 1);
200 lazy
.lock().unwrap().0 = 21;
202 assert_eq
!(lazy
.lock().unwrap().0, 21);
203 assert_eq
!(CALLED
.load(SeqCst
), 1);
207 fn static_sync_lazy() {
208 static XS
: SyncLazy
<Vec
<i32>> = SyncLazy
::new(|| {
209 let mut xs
= Vec
::new();
217 assert_eq
!(&*XS
, &vec
![1, 2, 3]);
220 assert_eq
!(&*XS
, &vec
![1, 2, 3]);
224 fn static_sync_lazy_via_fn() {
225 fn xs() -> &'
static Vec
<i32> {
226 static XS
: SyncOnceCell
<Vec
<i32>> = SyncOnceCell
::new();
228 let mut xs
= Vec
::new();
235 assert_eq
!(xs(), &vec
![1, 2, 3]);
239 fn sync_lazy_poisoning() {
240 let x
: SyncLazy
<String
> = SyncLazy
::new(|| panic
!("kaboom"));
242 let res
= panic
::catch_unwind(|| x
.len());
243 assert
!(res
.is_err());
249 fn assert_traits
<T
: Send
+ Sync
>() {}
250 assert_traits
::<SyncOnceCell
<String
>>();
251 assert_traits
::<SyncLazy
<String
>>();
255 fn eval_once_macro() {
256 macro_rules
! eval_once
{
260 static ONCE_CELL
: SyncOnceCell
<$ty
> = SyncOnceCell
::new();
264 ONCE_CELL
.get_or_init(init
)
268 let fib
: &'
static Vec
<i32> = eval_once
! {
270 let mut res
= vec
![1, 1];
272 let next
= res
[i
] + res
[i
+ 1];
278 assert_eq
!(fib
[5], 8)
282 fn sync_once_cell_does_not_leak_partially_constructed_boxes() {
283 static ONCE_CELL
: SyncOnceCell
<String
> = SyncOnceCell
::new();
287 const MSG
: &str = "Hello, World";
289 let (tx
, rx
) = channel();
291 for _
in 0..n_readers
{
293 thread
::spawn(move || {
295 if let Some(msg
) = ONCE_CELL
.get() {
296 tx
.send(msg
).unwrap();
299 #[cfg(target_env = "sgx")]
300 crate::thread
::yield_now();
304 for _
in 0..n_writers
{
305 thread
::spawn(move || {
306 let _
= ONCE_CELL
.set(MSG
.to_owned());
310 for _
in 0..n_readers
{
311 let msg
= rx
.recv().unwrap();
312 assert_eq
!(msg
, MSG
);
318 let cell
= SyncOnceCell
::new();
320 let s
= String
::new();
321 cell
.set(&s
).unwrap();