spin/once.rs
1//! Synchronization primitives for one-time evaluation.
2
3use crate::{
4 atomic::{AtomicU8, Ordering},
5 RelaxStrategy, Spin,
6};
7use core::{
8 cell::UnsafeCell,
9 fmt,
10 marker::PhantomData,
11 mem::{ManuallyDrop, MaybeUninit},
12};
13
14/// A primitive that provides lazy one-time initialization.
15///
16/// Unlike its `std::sync` equivalent, this is generalized such that the closure returns a
17/// value to be stored by the [`Once`] (`std::sync::Once` can be trivially emulated with
18/// `Once`).
19///
20/// Because [`Once::new`] is `const`, this primitive may be used to safely initialize statics.
21///
22/// # Examples
23///
24/// ```
25/// use spin;
26///
27/// static START: spin::Once = spin::Once::new();
28///
29/// START.call_once(|| {
30/// // run initialization here
31/// });
32/// ```
33pub struct Once<T = (), R = Spin> {
34 phantom: PhantomData<R>,
35 status: AtomicStatus,
36 data: UnsafeCell<MaybeUninit<T>>,
37}
38
39impl<T, R> Default for Once<T, R> {
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45impl<T: fmt::Debug, R> fmt::Debug for Once<T, R> {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 let mut d = f.debug_tuple("Once");
48 let d = if let Some(x) = self.get() {
49 d.field(&x)
50 } else {
51 d.field(&format_args!("<uninit>"))
52 };
53 d.finish()
54 }
55}
56
57// Same unsafe impls as `std::sync::RwLock`, because this also allows for
58// concurrent reads.
59unsafe impl<T: Send + Sync, R> Sync for Once<T, R> {}
60unsafe impl<T: Send, R> Send for Once<T, R> {}
61
62mod status {
63 use super::*;
64
65 // SAFETY: This structure has an invariant, namely that the inner atomic u8 must *always* have
66 // a value for which there exists a valid Status. This means that users of this API must only
67 // be allowed to load and store `Status`es.
68 #[repr(transparent)]
69 pub struct AtomicStatus(AtomicU8);
70
71 // Four states that a Once can be in, encoded into the lower bits of `status` in
72 // the Once structure.
73 #[repr(u8)]
74 #[derive(Clone, Copy, Debug, PartialEq)]
75 pub enum Status {
76 Incomplete = 0x00,
77 Running = 0x01,
78 Complete = 0x02,
79 Panicked = 0x03,
80 }
81 impl Status {
82 // Construct a status from an inner u8 integer.
83 //
84 // # Safety
85 //
86 // For this to be safe, the inner number must have a valid corresponding enum variant.
87 unsafe fn new_unchecked(inner: u8) -> Self {
88 core::mem::transmute(inner)
89 }
90 }
91
92 impl AtomicStatus {
93 #[inline(always)]
94 pub const fn new(status: Status) -> Self {
95 // SAFETY: We got the value directly from status, so transmuting back is fine.
96 Self(AtomicU8::new(status as u8))
97 }
98 #[inline(always)]
99 pub fn load(&self, ordering: Ordering) -> Status {
100 // SAFETY: We know that the inner integer must have been constructed from a Status in
101 // the first place.
102 unsafe { Status::new_unchecked(self.0.load(ordering)) }
103 }
104 #[inline(always)]
105 pub fn store(&self, status: Status, ordering: Ordering) {
106 // SAFETY: While not directly unsafe, this is safe because the value was retrieved from
107 // a status, thus making transmutation safe.
108 self.0.store(status as u8, ordering);
109 }
110 #[inline(always)]
111 pub fn compare_exchange(
112 &self,
113 old: Status,
114 new: Status,
115 success: Ordering,
116 failure: Ordering,
117 ) -> Result<Status, Status> {
118 match self
119 .0
120 .compare_exchange(old as u8, new as u8, success, failure)
121 {
122 // SAFETY: A compare exchange will always return a value that was later stored into
123 // the atomic u8, but due to the invariant that it must be a valid Status, we know
124 // that both Ok(_) and Err(_) will be safely transmutable.
125 Ok(ok) => Ok(unsafe { Status::new_unchecked(ok) }),
126 Err(err) => Err(unsafe { Status::new_unchecked(err) }),
127 }
128 }
129 #[inline(always)]
130 pub fn get_mut(&mut self) -> &mut Status {
131 // SAFETY: Since we know that the u8 inside must be a valid Status, we can safely cast
132 // it to a &mut Status.
133 unsafe { &mut *((self.0.get_mut() as *mut u8).cast::<Status>()) }
134 }
135 }
136}
137use self::status::{AtomicStatus, Status};
138
139/// The result after trying to update the atomic status to begin initialization.
140#[derive(Clone, Copy, Debug)]
141enum BeginInit<'a, T> {
142 /// The status was successfully updated
143 Started,
144 /// The status was not updated, the caller should try again
145 Retry,
146 /// The cell was already initialized
147 Done(&'a T),
148}
149
150impl<T, R: RelaxStrategy> Once<T, R> {
151 /// Performs an initialization routine once and only once. The given closure
152 /// will be executed if this is the first time `call_once` has been called,
153 /// and otherwise the routine will *not* be invoked.
154 ///
155 /// This method will block the calling thread if another initialization
156 /// routine is currently running.
157 ///
158 /// When this function returns, it is guaranteed that some initialization
159 /// has run and completed (it may not be the closure specified). The
160 /// returned pointer will point to the result from the closure that was
161 /// run.
162 ///
163 /// # Panics
164 ///
165 /// This function will panic if the [`Once`] previously panicked while attempting
166 /// to initialize. This is similar to the poisoning behaviour of `std::sync`'s
167 /// primitives.
168 ///
169 /// # Examples
170 ///
171 /// ```
172 /// use spin;
173 ///
174 /// static INIT: spin::Once<usize> = spin::Once::new();
175 ///
176 /// fn get_cached_val() -> usize {
177 /// *INIT.call_once(expensive_computation)
178 /// }
179 ///
180 /// fn expensive_computation() -> usize {
181 /// // ...
182 /// # 2
183 /// }
184 /// ```
185 pub fn call_once<F: FnOnce() -> T>(&self, f: F) -> &T {
186 match self.try_call_once(|| Ok::<T, core::convert::Infallible>(f())) {
187 Ok(x) => x,
188 Err(void) => match void {},
189 }
190 }
191
192 /// This method is similar to `call_once`, but allows the given closure to
193 /// fail, and leaves the `Once` in a uninitialized state if it does.
194 ///
195 /// This method will block the calling thread if another initialization
196 /// routine is currently running.
197 ///
198 /// When this function returns without error, it is guaranteed that some
199 /// initialization has run and completed (it may not be the closure
200 /// specified). The returned reference will point to the result from the
201 /// closure that was run.
202 ///
203 /// # Panics
204 ///
205 /// This function will panic if the [`Once`] previously panicked while attempting
206 /// to initialize. This is similar to the poisoning behaviour of `std::sync`'s
207 /// primitives.
208 ///
209 /// # Examples
210 ///
211 /// ```
212 /// use spin;
213 ///
214 /// static INIT: spin::Once<usize> = spin::Once::new();
215 ///
216 /// fn get_cached_val() -> Result<usize, String> {
217 /// INIT.try_call_once(expensive_fallible_computation).map(|x| *x)
218 /// }
219 ///
220 /// fn expensive_fallible_computation() -> Result<usize, String> {
221 /// // ...
222 /// # Ok(2)
223 /// }
224 /// ```
225 pub fn try_call_once<F: FnOnce() -> Result<T, E>, E>(&self, f: F) -> Result<&T, E> {
226 if let Some(value) = self.get() {
227 Ok(value)
228 } else {
229 self.try_call_once_slow(f)
230 }
231 }
232
233 /// Initializes the cell from a reference to the given value. If the cell is already
234 /// initialized, it returns the previous value.
235 ///
236 /// This method may help avoiding expensive stack copies on debug builds if
237 /// `T` is big enough.
238 ///
239 /// ```
240 /// #[derive(Clone, Copy, Debug)]
241 /// struct MyType([u8; 4096]);
242 ///
243 /// static INIT: spin::Once<MyType> = spin::Once::new();
244 ///
245 /// fn init_from_box(boxed: Box<MyType>) {
246 /// INIT.init_from_ref(&boxed);
247 /// }
248 /// ```
249 pub fn init_from_ref(&self, value: &T) -> &T
250 where
251 T: Copy,
252 {
253 if let Some(value) = self.get() {
254 value
255 } else {
256 self.init_from_ref_slow(value)
257 }
258 }
259
260 /// Attempts begin the initialization process by updating `self.status`.
261 fn try_begin_init(&self) -> BeginInit<'_, T> {
262 match self.status.compare_exchange(
263 Status::Incomplete,
264 Status::Running,
265 Ordering::Acquire,
266 Ordering::Acquire,
267 ) {
268 Ok(_) => BeginInit::Started,
269 Err(Status::Panicked) => panic!("Once panicked"),
270 Err(Status::Running) => match self.poll() {
271 Some(v) => BeginInit::Done(v),
272 None => BeginInit::Retry,
273 },
274 Err(Status::Complete) => {
275 BeginInit::Done(unsafe {
276 // SAFETY: The status is Complete
277 self.force_get()
278 })
279 }
280 Err(Status::Incomplete) => {
281 // The compare_exchange failed, so this shouldn't ever be reached,
282 // however if we decide to switch to compare_exchange_weak it will
283 // be safer to leave this here than hit an unreachable
284 BeginInit::Retry
285 }
286 }
287 }
288
289 /// Complete the initialization process.
290 ///
291 /// # Safety
292 ///
293 /// The internal status must have been previously set to `Running` and the
294 /// internal cell properly initialized.
295 #[inline]
296 unsafe fn complete_init(&self) -> &T {
297 // SAFETY: Release is required here, so that all memory accesses done in the
298 // closure when initializing, become visible to other threads that perform Acquire
299 // loads.
300 //
301 // And, we also know that the changes this thread has done will not magically
302 // disappear from our cache, so it does not need to be AcqRel.
303 self.status.store(Status::Complete, Ordering::Release);
304
305 // This next line is mainly an optimization.
306 // SAFETY: the caller must have made sure that the cell was
307 // initialized.
308 unsafe { self.force_get() }
309 }
310
311 fn init_from_ref_slow(&self, value: &T) -> &T
312 where
313 T: Copy,
314 {
315 loop {
316 match self.try_begin_init() {
317 BeginInit::Started => break,
318 BeginInit::Retry => continue,
319 BeginInit::Done(v) => return v,
320 }
321 }
322 // SAFETY: `UnsafeCell`/deref: currently the only accessor, mutably
323 // and immutably by cas exclusion.
324 // `write`: pointer comes from `MaybeUninit`.
325 // We've made sure to set the internal atomic status to `Running`, and
326 // we initialize the cell before calling complete_init().
327 unsafe {
328 (*self.data.get())
329 .as_mut_ptr()
330 .copy_from_nonoverlapping(value, 1);
331 self.complete_init()
332 }
333 }
334
335 #[cold]
336 fn try_call_once_slow<F: FnOnce() -> Result<T, E>, E>(&self, f: F) -> Result<&T, E> {
337 loop {
338 match self.try_begin_init() {
339 BeginInit::Started => {
340 // Impl is defined after the match for readability
341 }
342 BeginInit::Retry => continue,
343 BeginInit::Done(v) => return Ok(v),
344 }
345
346 // The compare-exchange succeeded, so we shall initialize it.
347
348 // We use a guard (Finish) to catch panics caused by builder
349 let finish = Finish {
350 status: &self.status,
351 };
352 let val = match f() {
353 Ok(val) => val,
354 Err(err) => {
355 // If an error occurs, clean up everything and leave.
356 core::mem::forget(finish);
357 self.status.store(Status::Incomplete, Ordering::Release);
358 return Err(err);
359 }
360 };
361 unsafe {
362 // SAFETY:
363 // `UnsafeCell`/deref: currently the only accessor, mutably
364 // and immutably by cas exclusion.
365 // `write`: pointer comes from `MaybeUninit`.
366 (*self.data.get()).as_mut_ptr().write(val);
367 };
368 // If there were to be a panic with unwind enabled, the code would
369 // short-circuit and never reach the point where it writes the inner data.
370 // The destructor for Finish will run, and poison the Once to ensure that other
371 // threads accessing it do not exhibit unwanted behavior, if there were to be
372 // any inconsistency in data structures caused by the panicking thread.
373 //
374 // However, f() is expected in the general case not to panic. In that case, we
375 // simply forget the guard, bypassing its destructor. We could theoretically
376 // clear a flag instead, but this eliminates the call to the destructor at
377 // compile time, and unconditionally poisons during an eventual panic, if
378 // unwinding is enabled.
379 core::mem::forget(finish);
380
381 // SAFETY: we have made sure to set the internal state via
382 // `try_begin_init()` and we have initialized the cell above.
383 return unsafe { Ok(self.complete_init()) };
384 }
385 }
386
387 /// Spins until the [`Once`] contains a value.
388 ///
389 /// Note that in releases prior to `0.7`, this function had the behaviour of [`Once::poll`].
390 ///
391 /// # Panics
392 ///
393 /// This function will panic if the [`Once`] previously panicked while attempting
394 /// to initialize. This is similar to the poisoning behaviour of `std::sync`'s
395 /// primitives.
396 pub fn wait(&self) -> &T {
397 loop {
398 match self.poll() {
399 Some(x) => break x,
400 None => R::relax(),
401 }
402 }
403 }
404
405 /// Like [`Once::get`], but will spin if the [`Once`] is in the process of being
406 /// initialized. If initialization has not even begun, `None` will be returned.
407 ///
408 /// Note that in releases prior to `0.7`, this function was named `wait`.
409 ///
410 /// # Panics
411 ///
412 /// This function will panic if the [`Once`] previously panicked while attempting
413 /// to initialize. This is similar to the poisoning behaviour of `std::sync`'s
414 /// primitives.
415 pub fn poll(&self) -> Option<&T> {
416 loop {
417 // SAFETY: Acquire is safe here, because if the status is COMPLETE, then we want to make
418 // sure that all memory accessed done while initializing that value, are visible when
419 // we return a reference to the inner data after this load.
420 match self.status.load(Ordering::Acquire) {
421 Status::Incomplete => return None,
422 Status::Running => R::relax(), // We spin
423 Status::Complete => return Some(unsafe { self.force_get() }),
424 Status::Panicked => panic!("Once previously poisoned by a panicked"),
425 }
426 }
427 }
428}
429
430impl<T, R> Once<T, R> {
431 /// Initialization constant of [`Once`].
432 #[allow(clippy::declare_interior_mutable_const)]
433 pub const INIT: Self = Self {
434 phantom: PhantomData,
435 status: AtomicStatus::new(Status::Incomplete),
436 data: UnsafeCell::new(MaybeUninit::uninit()),
437 };
438
439 /// Creates a new [`Once`].
440 pub const fn new() -> Self {
441 Self::INIT
442 }
443
444 /// Creates a new initialized [`Once`].
445 pub const fn initialized(data: T) -> Self {
446 Self {
447 phantom: PhantomData,
448 status: AtomicStatus::new(Status::Complete),
449 data: UnsafeCell::new(MaybeUninit::new(data)),
450 }
451 }
452
453 /// Retrieve a pointer to the inner data.
454 ///
455 /// While this method itself is safe, accessing the pointer before the [`Once`] has been
456 /// initialized is UB, unless this method has already been written to from a pointer coming
457 /// from this method.
458 pub fn as_mut_ptr(&self) -> *mut T {
459 // SAFETY:
460 // * MaybeUninit<T> always has exactly the same layout as T
461 self.data.get().cast::<T>()
462 }
463
464 /// Get a reference to the initialized instance. Must only be called once COMPLETE.
465 unsafe fn force_get(&self) -> &T {
466 // SAFETY:
467 // * `UnsafeCell`/inner deref: data never changes again
468 // * `MaybeUninit`/outer deref: data was initialized
469 &*(*self.data.get()).as_ptr()
470 }
471
472 /// Get a reference to the initialized instance. Must only be called once COMPLETE.
473 unsafe fn force_get_mut(&mut self) -> &mut T {
474 // SAFETY:
475 // * `UnsafeCell`/inner deref: data never changes again
476 // * `MaybeUninit`/outer deref: data was initialized
477 &mut *(*self.data.get()).as_mut_ptr()
478 }
479
480 /// Get a reference to the initialized instance. Must only be called once COMPLETE.
481 unsafe fn force_into_inner(self) -> T {
482 let mut this = ManuallyDrop::new(self);
483 // SAFETY:
484 // * `UnsafeCell`/inner deref: data never changes again
485 // * `MaybeUninit`/outer deref: data was initialized
486 // * We never call `self`'s destructor, ensuring a double-drop cannot occur.
487 this.data.get_mut().assume_init_read()
488 }
489
490 /// Returns a reference to the inner value if the [`Once`] has been initialized.
491 pub fn get(&self) -> Option<&T> {
492 // SAFETY: Just as with `poll`, Acquire is safe here because we want to be able to see the
493 // nonatomic stores done when initializing, once we have loaded and checked the status.
494 match self.status.load(Ordering::Acquire) {
495 Status::Complete => Some(unsafe { self.force_get() }),
496 _ => None,
497 }
498 }
499
500 /// Returns a reference to the inner value on the unchecked assumption that the [`Once`] has been initialized.
501 ///
502 /// # Safety
503 ///
504 /// This is *extremely* unsafe if the `Once` has not already been initialized because a reference to uninitialized
505 /// memory will be returned, immediately triggering undefined behaviour (even if the reference goes unused).
506 /// However, this can be useful in some instances for exposing the `Once` to FFI or when the overhead of atomically
507 /// checking initialization is unacceptable and the `Once` has already been initialized.
508 pub unsafe fn get_unchecked(&self) -> &T {
509 debug_assert_eq!(
510 self.status.load(Ordering::SeqCst),
511 Status::Complete,
512 "Attempted to access an uninitialized Once. If this was run without debug checks, this would be undefined behaviour. This is a serious bug and you must fix it.",
513 );
514 self.force_get()
515 }
516
517 /// Returns a mutable reference to the inner value if the [`Once`] has been initialized.
518 ///
519 /// Because this method requires a mutable reference to the [`Once`], no synchronization
520 /// overhead is required to access the inner value. In effect, it is zero-cost.
521 pub fn get_mut(&mut self) -> Option<&mut T> {
522 match *self.status.get_mut() {
523 Status::Complete => Some(unsafe { self.force_get_mut() }),
524 _ => None,
525 }
526 }
527
528 /// Returns a mutable reference to the inner value
529 ///
530 /// # Safety
531 ///
532 /// This is *extremely* unsafe if the `Once` has not already been initialized because a reference to uninitialized
533 /// memory will be returned, immediately triggering undefined behaviour (even if the reference goes unused).
534 /// However, this can be useful in some instances for exposing the `Once` to FFI or when the overhead of atomically
535 /// checking initialization is unacceptable and the `Once` has already been initialized.
536 pub unsafe fn get_mut_unchecked(&mut self) -> &mut T {
537 debug_assert_eq!(
538 self.status.load(Ordering::SeqCst),
539 Status::Complete,
540 "Attempted to access an uninitialized Once. If this was to run without debug checks, this would be undefined behavior. This is a serious bug and you must fix it.",
541 );
542 self.force_get_mut()
543 }
544
545 /// Returns a the inner value if the [`Once`] has been initialized.
546 ///
547 /// Because this method requires ownership of the [`Once`], no synchronization overhead
548 /// is required to access the inner value. In effect, it is zero-cost.
549 pub fn try_into_inner(mut self) -> Option<T> {
550 match *self.status.get_mut() {
551 Status::Complete => Some(unsafe { self.force_into_inner() }),
552 _ => None,
553 }
554 }
555
556 /// Returns a the inner value if the [`Once`] has been initialized.
557 /// # Safety
558 ///
559 /// This is *extremely* unsafe if the `Once` has not already been initialized because a reference to uninitialized
560 /// memory will be returned, immediately triggering undefined behaviour (even if the reference goes unused)
561 /// This can be useful, if `Once` has already been initialized, and you want to bypass an
562 /// option check.
563 pub unsafe fn into_inner_unchecked(self) -> T {
564 debug_assert_eq!(
565 self.status.load(Ordering::SeqCst),
566 Status::Complete,
567 "Attempted to access an uninitialized Once. If this was to run without debug checks, this would be undefined behavior. This is a serious bug and you must fix it.",
568 );
569 self.force_into_inner()
570 }
571
572 /// Checks whether the value has been initialized.
573 ///
574 /// This is done using [`Acquire`](core::sync::atomic::Ordering::Acquire) ordering, and
575 /// therefore it is safe to access the value directly via
576 /// [`get_unchecked`](Self::get_unchecked) if this returns true.
577 pub fn is_completed(&self) -> bool {
578 // TODO: Add a similar variant for Relaxed?
579 self.status.load(Ordering::Acquire) == Status::Complete
580 }
581}
582
583impl<T, R> From<T> for Once<T, R> {
584 fn from(data: T) -> Self {
585 Self::initialized(data)
586 }
587}
588
589impl<T, R> Drop for Once<T, R> {
590 fn drop(&mut self) {
591 // No need to do any atomic access here, we have &mut!
592 if *self.status.get_mut() == Status::Complete {
593 unsafe { self.data.get_mut().assume_init_drop() }
594 }
595 }
596}
597
598struct Finish<'a> {
599 status: &'a AtomicStatus,
600}
601
602impl<'a> Drop for Finish<'a> {
603 fn drop(&mut self) {
604 // While using Relaxed here would most likely not be an issue, we use SeqCst anyway.
605 // This is mainly because panics are not meant to be fast at all, but also because if
606 // there were to be a compiler bug which reorders accesses within the same thread,
607 // where it should not, we want to be sure that the panic really is handled, and does
608 // not cause additional problems. SeqCst will therefore help guarding against such
609 // bugs.
610 self.status.store(Status::Panicked, Ordering::SeqCst);
611 }
612}
613
614#[cfg(test)]
615mod tests {
616 use std::prelude::v1::*;
617
618 use std::sync::atomic::AtomicU32;
619 use std::sync::mpsc::channel;
620 use std::sync::Arc;
621 use std::thread;
622
623 use super::*;
624
625 #[test]
626 fn smoke_once() {
627 static O: Once = Once::new();
628 let mut a = 0;
629 O.call_once(|| a += 1);
630 assert_eq!(a, 1);
631 O.call_once(|| a += 1);
632 assert_eq!(a, 1);
633 }
634
635 #[test]
636 fn smoke_once_value() {
637 static O: Once<usize> = Once::new();
638 let a = O.call_once(|| 1);
639 assert_eq!(*a, 1);
640 let b = O.call_once(|| 2);
641 assert_eq!(*b, 1);
642 }
643
644 #[test]
645 fn stampede_once() {
646 static O: Once = Once::new();
647 static mut RUN: bool = false;
648
649 let (tx, rx) = channel();
650 let mut ts = Vec::new();
651 for _ in 0..10 {
652 let tx = tx.clone();
653 ts.push(thread::spawn(move || {
654 for _ in 0..4 {
655 thread::yield_now()
656 }
657 unsafe {
658 O.call_once(|| {
659 assert!(!RUN);
660 RUN = true;
661 });
662 assert!(RUN);
663 }
664 tx.send(()).unwrap();
665 }));
666 }
667
668 unsafe {
669 O.call_once(|| {
670 assert!(!RUN);
671 RUN = true;
672 });
673 assert!(RUN);
674 }
675
676 for _ in 0..10 {
677 rx.recv().unwrap();
678 }
679
680 for t in ts {
681 t.join().unwrap();
682 }
683 }
684
685 #[test]
686 fn get() {
687 static INIT: Once<usize> = Once::new();
688
689 assert!(INIT.get().is_none());
690 INIT.call_once(|| 2);
691 assert_eq!(INIT.get().copied(), Some(2));
692 }
693
694 #[test]
695 fn get_no_wait() {
696 static INIT: Once<usize> = Once::new();
697
698 assert!(INIT.get().is_none());
699 let t = thread::spawn(move || {
700 INIT.call_once(|| {
701 thread::sleep(std::time::Duration::from_secs(3));
702 42
703 });
704 });
705 assert!(INIT.get().is_none());
706
707 t.join().unwrap();
708 }
709
710 #[test]
711 fn poll() {
712 static INIT: Once<usize> = Once::new();
713
714 assert!(INIT.poll().is_none());
715 INIT.call_once(|| 3);
716 assert_eq!(INIT.poll().copied(), Some(3));
717 }
718
719 #[test]
720 fn wait() {
721 static INIT: Once<usize> = Once::new();
722
723 let t = std::thread::spawn(|| {
724 assert_eq!(*INIT.wait(), 3);
725 assert!(INIT.is_completed());
726 });
727
728 for _ in 0..4 {
729 thread::yield_now()
730 }
731
732 assert!(INIT.poll().is_none());
733 INIT.call_once(|| 3);
734
735 t.join().unwrap();
736 }
737
738 #[test]
739 fn panic() {
740 use std::panic;
741
742 static INIT: Once = Once::new();
743
744 // poison the once
745 let t = panic::catch_unwind(|| {
746 INIT.call_once(|| panic!());
747 });
748 assert!(t.is_err());
749
750 // poisoning propagates
751 let t = panic::catch_unwind(|| {
752 INIT.call_once(|| {});
753 });
754 assert!(t.is_err());
755 }
756
757 #[test]
758 fn init_constant() {
759 static O: Once = Once::INIT;
760 let mut a = 0;
761 O.call_once(|| a += 1);
762 assert_eq!(a, 1);
763 O.call_once(|| a += 1);
764 assert_eq!(a, 1);
765 }
766
767 static mut CALLED: bool = false;
768
769 struct DropTest {}
770
771 impl Drop for DropTest {
772 fn drop(&mut self) {
773 unsafe {
774 CALLED = true;
775 }
776 }
777 }
778
779 #[test]
780 fn try_call_once_err() {
781 let once = Once::<_, Spin>::new();
782 let shared = Arc::new((once, AtomicU32::new(0)));
783
784 let (tx, rx) = channel();
785
786 let t0 = {
787 let shared = shared.clone();
788 thread::spawn(move || {
789 let (once, called) = &*shared;
790
791 once.try_call_once(|| {
792 called.fetch_add(1, Ordering::AcqRel);
793 tx.send(()).unwrap();
794 thread::sleep(std::time::Duration::from_millis(50));
795 Err(())
796 })
797 .ok();
798 })
799 };
800
801 let t1 = {
802 let shared = shared.clone();
803 thread::spawn(move || {
804 rx.recv().unwrap();
805 let (once, called) = &*shared;
806 assert_eq!(
807 called.load(Ordering::Acquire),
808 1,
809 "leader thread did not run first"
810 );
811
812 once.call_once(|| {
813 called.fetch_add(1, Ordering::AcqRel);
814 });
815 })
816 };
817
818 t0.join().unwrap();
819 t1.join().unwrap();
820
821 assert_eq!(shared.1.load(Ordering::Acquire), 2);
822 }
823
824 // This is sort of two test cases, but if we write them as separate test methods
825 // they can be executed concurrently and then fail some small fraction of the
826 // time.
827 #[test]
828 fn drop_occurs_and_skip_uninit_drop() {
829 unsafe {
830 CALLED = false;
831 }
832
833 {
834 let once = Once::<_>::new();
835 once.call_once(|| DropTest {});
836 }
837
838 assert!(unsafe { CALLED });
839 // Now test that we skip drops for the uninitialized case.
840 unsafe {
841 CALLED = false;
842 }
843
844 let once = Once::<DropTest>::new();
845 drop(once);
846
847 assert!(unsafe { !CALLED });
848 }
849
850 #[test]
851 fn call_once_test() {
852 for _ in 0..20 {
853 use std::sync::atomic::AtomicUsize;
854 use std::sync::Arc;
855 use std::time::Duration;
856 let share = Arc::new(AtomicUsize::new(0));
857 let once = Arc::new(Once::<_, Spin>::new());
858 let mut hs = Vec::new();
859 for _ in 0..8 {
860 let h = thread::spawn({
861 let share = share.clone();
862 let once = once.clone();
863 move || {
864 thread::sleep(Duration::from_millis(10));
865 once.call_once(|| {
866 share.fetch_add(1, Ordering::SeqCst);
867 });
868 }
869 });
870 hs.push(h);
871 }
872 for h in hs {
873 h.join().unwrap();
874 }
875 assert_eq!(1, share.load(Ordering::SeqCst));
876 }
877 }
878
879 #[test]
880 fn init_from_ref_basic() {
881 let once = Once::<usize, Spin>::new();
882
883 let first = 1usize;
884 let second = 2usize;
885 assert_eq!(*once.init_from_ref(&first), 1);
886 assert_eq!(*once.init_from_ref(&second), 1);
887 }
888
889 #[test]
890 fn drop_boxed() {
891 let boxed = Box::new(5);
892 let once = Once::<_, Spin>::initialized(boxed);
893 let boxed = once.try_into_inner().unwrap();
894 println!("{}", boxed);
895 }
896}