Skip to main content

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}