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