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