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