Skip to main content

parking_lot/
once.rs

1use core::{
2    fmt, mem,
3    sync::atomic::{AtomicU8, Ordering, fence},
4};
5use parking_lot_core::{self, DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN, SpinWait};
6
7use crate::deadlock;
8
9const DONE_BIT: u8 = 1;
10const POISON_BIT: u8 = 2;
11const LOCKED_BIT: u8 = 4;
12const PARKED_BIT: u8 = 8;
13
14/// Current state of a `Once`.
15#[derive(#[automatically_derived]impl ::core::marker::Copy for OnceState { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for OnceState {
}
#[automatically_derived]impl ::core::clone::Clone for OnceState {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::cmp::Eq for OnceState { }Eq, #[automatically_derived]impl ::core::marker::StructuralPartialEq for OnceState
    {
}
#[automatically_derived]impl ::core::cmp::PartialEq for OnceState {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, #[automatically_derived]impl ::core::fmt::Debug for OnceState {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                OnceState::New => "New",
                OnceState::Poisoned => "Poisoned",
                OnceState::InProgress => "InProgress",
                OnceState::Done => "Done",
            })
    }
}Debug)]
16pub enum OnceState {
17    /// A closure has not been executed yet.
18    New,
19
20    /// A closure was executed but panicked.
21    Poisoned,
22
23    /// A thread is currently executing a closure.
24    InProgress,
25
26    /// A closure has completed successfully.
27    Done,
28}
29
30impl OnceState {
31    /// Returns `true` if this is the [`Poisoned`](OnceState::Poisoned) state.
32    /// When a state is passed to [`Once::call_once_force`], this indicates that
33    /// the [`Once`] was poisoned before the closure was invoked.
34    ///
35    /// # Examples
36    ///
37    /// A poisoned [`Once`]:
38    ///
39    /// ```
40    /// use parking_lot::Once;
41    /// use std::thread;
42    ///
43    /// static INIT: Once = Once::new();
44    ///
45    /// let handle = thread::spawn(|| {
46    ///     INIT.call_once(|| panic!());
47    /// });
48    /// assert!(handle.join().is_err());
49    ///
50    /// INIT.call_once_force(|state| {
51    ///     assert!(state.is_poisoned());
52    /// });
53    /// ```
54    ///
55    /// An unpoisoned [`Once`]:
56    ///
57    /// ```
58    /// use parking_lot::Once;
59    ///
60    /// static INIT: Once = Once::new();
61    ///
62    /// INIT.call_once_force(|state| {
63    ///     assert!(!state.is_poisoned());
64    /// });
65    /// ```
66    #[inline]
67    pub const fn is_poisoned(self) -> bool {
68        #[allow(non_exhaustive_omitted_patterns)] match self {
    OnceState::Poisoned => true,
    _ => false,
}matches!(self, OnceState::Poisoned)
69    }
70
71    /// Alias for [`is_poisoned`](Self::is_poisoned).
72    #[inline]
73    pub const fn poisoned(self) -> bool {
74        self.is_poisoned()
75    }
76
77    /// Returns `true` if this is the [`Done`](OnceState::Done) state.
78    #[inline]
79    pub const fn is_completed(self) -> bool {
80        #[allow(non_exhaustive_omitted_patterns)] match self {
    OnceState::Done => true,
    _ => false,
}matches!(self, OnceState::Done)
81    }
82
83    /// Alias for [`is_completed`](Self::is_completed).
84    #[inline]
85    pub const fn done(self) -> bool {
86        self.is_completed()
87    }
88}
89
90/// A synchronization primitive which can be used to run a one-time
91/// initialization. Useful for one-time initialization for globals, FFI or
92/// related functionality.
93///
94/// When the initialization produces a value, [`std::sync::OnceLock`] is often
95/// more convenient.
96///
97/// # Examples
98///
99/// ```
100/// use parking_lot::Once;
101///
102/// static START: Once = Once::new();
103///
104/// START.call_once(|| {
105///     // run initialization here
106/// });
107/// ```
108pub struct Once(AtomicU8);
109
110impl Once {
111    /// Creates a new `Once` value.
112    #[inline]
113    pub const fn new() -> Once {
114        Once(AtomicU8::new(0))
115    }
116
117    /// Creates a new `Once` value that is already in the completed state.
118    ///
119    /// A `Once` created this way will never invoke a closure passed to
120    /// [`call_once`](Self::call_once) or [`call_once_force`](Self::call_once_force),
121    /// and its [`state`](Self::state) will always be [`OnceState::Done`].
122    ///
123    /// # Examples
124    ///
125    /// ```
126    /// use parking_lot::{Once, OnceState};
127    ///
128    /// static INIT: Once = Once::new_completed();
129    /// assert_eq!(INIT.state(), OnceState::Done);
130    ///
131    /// // The closure is never executed.
132    /// INIT.call_once(|| unreachable!());
133    /// ```
134    #[inline]
135    pub const fn new_completed() -> Once {
136        Once(AtomicU8::new(DONE_BIT))
137    }
138
139    /// Returns a snapshot of the current state of this `Once`.
140    ///
141    /// The state may change immediately after this function returns.
142    #[inline]
143    pub fn state(&self) -> OnceState {
144        let state = self.0.load(Ordering::Acquire);
145        if state & DONE_BIT != 0 {
146            OnceState::Done
147        } else if state & LOCKED_BIT != 0 {
148            OnceState::InProgress
149        } else if state & POISON_BIT != 0 {
150            OnceState::Poisoned
151        } else {
152            OnceState::New
153        }
154    }
155
156    /// Returns `true` if this `Once` is in the completed state.
157    ///
158    /// A `Once` becomes completed when an initialization closure finishes
159    /// successfully, or when it is created with
160    /// [`new_completed`](Self::new_completed). This method returns `false` if
161    /// initialization has not started, is still in progress, or the `Once` is
162    /// poisoned.
163    ///
164    /// A `false` result may be stale. For example, initialization may complete
165    /// between the state being read and this function returning.
166    ///
167    /// # Examples
168    ///
169    /// ```
170    /// use parking_lot::Once;
171    ///
172    /// static INIT: Once = Once::new();
173    ///
174    /// assert!(!INIT.is_completed());
175    /// INIT.call_once(|| {
176    ///     assert!(!INIT.is_completed());
177    /// });
178    /// assert!(INIT.is_completed());
179    /// assert!(Once::new_completed().is_completed());
180    /// ```
181    ///
182    /// A poisoned [`Once`] has not completed successfully:
183    ///
184    /// ```
185    /// use parking_lot::Once;
186    /// use std::thread;
187    ///
188    /// static INIT: Once = Once::new();
189    ///
190    /// let handle = thread::spawn(|| {
191    ///     INIT.call_once(|| panic!());
192    /// });
193    /// assert!(handle.join().is_err());
194    /// assert!(!INIT.is_completed());
195    /// ```
196    #[inline]
197    pub fn is_completed(&self) -> bool {
198        self.0.load(Ordering::Acquire) & DONE_BIT != 0
199    }
200
201    /// Blocks the current thread until initialization has completed.
202    ///
203    /// Calling this method from an initialization closure for the same `Once`
204    /// may panic or deadlock.
205    ///
206    /// # Examples
207    ///
208    /// ```
209    /// use parking_lot::Once;
210    /// use std::thread;
211    ///
212    /// static READY: Once = Once::new();
213    ///
214    /// let thread = thread::spawn(|| {
215    ///     READY.wait();
216    ///     println!("everything is ready");
217    /// });
218    ///
219    /// READY.call_once(|| println!("performing setup"));
220    /// thread.join().unwrap();
221    /// ```
222    ///
223    /// # Panics
224    ///
225    /// If this `Once` has been poisoned because an initialization closure has
226    /// panicked, this method will also panic. Use
227    /// [`wait_force`](Self::wait_force) if this behavior is not desired.
228    #[inline]
229    pub fn wait(&self) {
230        if !self.is_completed() {
231            self.wait_slow(false);
232        }
233    }
234
235    /// Blocks the current thread until initialization has completed, ignoring
236    /// poisoning.
237    ///
238    /// If this `Once` has been poisoned, this function blocks until it becomes
239    /// completed, unlike [`Once::wait`], which panics in this case.
240    ///
241    /// Calling this method from an initialization closure for the same `Once`
242    /// may panic or deadlock.
243    #[inline]
244    pub fn wait_force(&self) {
245        if !self.is_completed() {
246            self.wait_slow(true);
247        }
248    }
249
250    /// Performs an initialization routine once and only once. The given closure
251    /// will be executed if this is the first time `call_once` has been called,
252    /// and otherwise the routine will *not* be invoked.
253    ///
254    /// This method will block the calling thread if another initialization
255    /// routine is currently running.
256    ///
257    /// When this function returns, the `Once` is in the completed state. Unless
258    /// it was created with [`new_completed`](Self::new_completed), some
259    /// initialization has run and completed, though it might not be the closure
260    /// specified. Any memory writes performed by the executed closure can be
261    /// reliably observed after this function returns; there is a happens-before
262    /// relation between the closure and code executing after the return.
263    ///
264    /// If the given closure recursively invokes `call_once` on the same `Once`
265    /// instance, the exact behavior is not specified: allowed outcomes are a
266    /// panic or a deadlock.
267    ///
268    /// # Examples
269    ///
270    /// ```
271    /// use parking_lot::Once;
272    ///
273    /// static mut VAL: usize = 0;
274    /// static INIT: Once = Once::new();
275    ///
276    /// // Accessing a `static mut` is unsafe much of the time, but if we do so
277    /// // in a synchronized fashion (e.g. write once or read all) then we're
278    /// // good to go!
279    /// //
280    /// // This function will only call `expensive_computation` once, and will
281    /// // otherwise always return the value returned from the first invocation.
282    /// fn get_cached_val() -> usize {
283    ///     unsafe {
284    ///         INIT.call_once(|| {
285    ///             VAL = expensive_computation();
286    ///         });
287    ///         VAL
288    ///     }
289    /// }
290    ///
291    /// fn expensive_computation() -> usize {
292    ///     // ...
293    /// # 2
294    /// }
295    /// ```
296    ///
297    /// # Panics
298    ///
299    /// The closure `f` will only be executed once even if this is called
300    /// concurrently amongst many threads. If that closure panics, however, then
301    /// it will *poison* this `Once` instance, causing all future invocations of
302    /// `call_once` to also panic.
303    #[inline]
304    pub fn call_once<F>(&self, f: F)
305    where
306        F: FnOnce(),
307    {
308        if self.0.load(Ordering::Acquire) == DONE_BIT {
309            return;
310        }
311
312        let mut f = Some(f);
313        self.call_once_slow(false, &mut |_| {
314            let f = f.take();
315            unsafe { f.unwrap_unchecked()() }
316        });
317    }
318
319    /// Performs the same function as [`call_once`](Self::call_once) except it
320    /// ignores poisoning.
321    ///
322    /// Unlike [`call_once`](Self::call_once), if this `Once` has been poisoned
323    /// by a previous initialization panic, this function will still invoke the
324    /// closure `f` instead of immediately panicking. If `f` panics, the `Once`
325    /// remains poisoned. If `f` does not panic, the `Once` is no longer
326    /// poisoned and all future calls to `call_once` or `call_once_force` are
327    /// no-ops.
328    ///
329    /// The closure `f` is passed a [`OnceState`] which can be used to query the
330    /// poison status of this `Once`.
331    ///
332    /// If the given closure recursively invokes `call_once` or
333    /// `call_once_force` on the same `Once` instance, the exact behavior is not
334    /// specified: allowed outcomes are a panic or a deadlock.
335    ///
336    /// # Examples
337    ///
338    /// ```
339    /// use parking_lot::Once;
340    /// use std::thread;
341    ///
342    /// static INIT: Once = Once::new();
343    ///
344    /// // Poison the once.
345    /// let handle = thread::spawn(|| {
346    ///     INIT.call_once(|| panic!());
347    /// });
348    /// assert!(handle.join().is_err());
349    ///
350    /// // Poisoning propagates.
351    /// let handle = thread::spawn(|| {
352    ///     INIT.call_once(|| {});
353    /// });
354    /// assert!(handle.join().is_err());
355    ///
356    /// // call_once_force still runs and clears the poisoned state.
357    /// INIT.call_once_force(|state| {
358    ///     assert!(state.is_poisoned());
359    /// });
360    ///
361    /// // Once initialization succeeds, future calls are no-ops.
362    /// INIT.call_once(|| {});
363    /// ```
364    #[inline]
365    pub fn call_once_force<F>(&self, f: F)
366    where
367        F: FnOnce(OnceState),
368    {
369        if self.0.load(Ordering::Acquire) == DONE_BIT {
370            return;
371        }
372
373        let mut f = Some(f);
374        self.call_once_slow(true, &mut |state| {
375            let f = f.take();
376            unsafe { f.unwrap_unchecked()(state) }
377        });
378    }
379
380    #[cold]
381    fn wait_slow(&self, ignore_poison: bool) {
382        let mut spinwait = SpinWait::new();
383        let mut state = self.0.load(Ordering::Relaxed);
384        loop {
385            if state & DONE_BIT != 0 {
386                // Synchronize with the initialization routine.
387                fence(Ordering::Acquire);
388                return;
389            }
390
391            if state & POISON_BIT != 0 && !ignore_poison {
392                fence(Ordering::Acquire);
393                {
    ::core::panicking::panic_fmt(format_args!("Once instance has previously been poisoned"));
};panic!("Once instance has previously been poisoned");
394            }
395
396            // Only spin while an initialization routine is actively running.
397            if state & LOCKED_BIT != 0 && state & PARKED_BIT == 0 && spinwait.spin() {
398                state = self.0.load(Ordering::Relaxed);
399                continue;
400            }
401
402            // Register that a thread may be parked. `try_update` rechecks the
403            // terminal states on every retry so we cannot miss completion or
404            // poisoning while setting PARKED_BIT.
405            match self
406                .0
407                .try_update(Ordering::Relaxed, Ordering::Relaxed, |state| {
408                    if state & DONE_BIT != 0 || (state & POISON_BIT != 0 && !ignore_poison) {
409                        None
410                    } else {
411                        Some(state | PARKED_BIT)
412                    }
413                }) {
414                Ok(_) => {}
415                Err(x) => {
416                    state = x;
417                    continue;
418                }
419            }
420
421            let addr = core::ptr::from_ref(self).addr();
422            let validate = || {
423                let state = self.0.load(Ordering::Relaxed);
424                state & PARKED_BIT != 0
425                    && state & DONE_BIT == 0
426                    && (ignore_poison || state & POISON_BIT == 0)
427            };
428            let before_sleep = || {};
429            let timed_out = |_, _| ::core::panicking::unreachable_default_msg()unreachable!();
430            // SAFETY:
431            // * `addr` is an address we control.
432            // * `validate` does not panic or call into `parking_lot`.
433            // * `before_sleep` does not call `park` or panic.
434            // * `timed_out` cannot be called because no timeout is specified.
435            unsafe {
436                parking_lot_core::park(
437                    addr,
438                    validate,
439                    before_sleep,
440                    timed_out,
441                    DEFAULT_PARK_TOKEN,
442                    None,
443                );
444            }
445
446            spinwait.reset();
447            state = self.0.load(Ordering::Relaxed);
448        }
449    }
450
451    // This is a non-generic function to reduce the monomorphization cost of
452    // using `call_once` (this isn't exactly a trivial or small implementation).
453    //
454    // Additionally, this is tagged with `#[cold]` as it should indeed be cold
455    // and it helps let LLVM know that calls to this function should be off the
456    // fast path. Essentially, this should help generate more straight line code
457    // in LLVM.
458    //
459    // Finally, this takes an `FnMut` instead of a `FnOnce` because there's
460    // currently no way to take an `FnOnce` and call it via virtual dispatch
461    // without some allocation overhead.
462    #[cold]
463    fn call_once_slow(&self, ignore_poison: bool, f: &mut dyn FnMut(OnceState)) {
464        let mut spinwait = SpinWait::new();
465        let mut state = self.0.load(Ordering::Relaxed);
466        loop {
467            // If another thread called the closure, we're done
468            if state & DONE_BIT != 0 {
469                // An acquire fence is needed here since we didn't load the
470                // state with Ordering::Acquire.
471                fence(Ordering::Acquire);
472                return;
473            }
474
475            // If the state has been poisoned and we aren't forcing, then panic
476            if state & POISON_BIT != 0 && !ignore_poison {
477                // Need the fence here as well for the same reason
478                fence(Ordering::Acquire);
479                {
    ::core::panicking::panic_fmt(format_args!("Once instance has previously been poisoned"));
};panic!("Once instance has previously been poisoned");
480            }
481
482            // Grab the lock if it isn't locked, even if there is a queue on it.
483            // We also clear the poison bit since we are going to try running
484            // the closure again.
485            if state & LOCKED_BIT == 0 {
486                match self.0.compare_exchange_weak(
487                    state,
488                    (state | LOCKED_BIT) & !POISON_BIT,
489                    Ordering::Acquire,
490                    Ordering::Relaxed,
491                ) {
492                    Ok(_) => break,
493                    Err(x) => state = x,
494                }
495                continue;
496            }
497
498            // If there is no queue, try spinning a few times
499            if state & PARKED_BIT == 0 && spinwait.spin() {
500                state = self.0.load(Ordering::Relaxed);
501                continue;
502            }
503
504            // Set the parked bit
505            if state & PARKED_BIT == 0
506                && let Err(x) = self.0.compare_exchange_weak(
507                    state,
508                    state | PARKED_BIT,
509                    Ordering::Relaxed,
510                    Ordering::Relaxed,
511                )
512            {
513                state = x;
514                continue;
515            }
516
517            // Park our thread until we are woken up by the thread that owns the
518            // lock.
519            let addr = core::ptr::from_ref(self).addr();
520            let validate = || self.0.load(Ordering::Relaxed) == LOCKED_BIT | PARKED_BIT;
521            let before_sleep = || {};
522            let timed_out = |_, _| ::core::panicking::unreachable_default_msg()unreachable!();
523            unsafe {
524                parking_lot_core::park(
525                    addr,
526                    validate,
527                    before_sleep,
528                    timed_out,
529                    DEFAULT_PARK_TOKEN,
530                    None,
531                );
532            }
533
534            // Loop back and check if the done bit was set
535            spinwait.reset();
536            state = self.0.load(Ordering::Relaxed);
537        }
538
539        struct PanicGuard<'a>(&'a Once);
540        impl<'a> Drop for PanicGuard<'a> {
541            fn drop(&mut self) {
542                // Stop recording ownership, mark the state as poisoned,
543                // unlock it and unpark all threads.
544                let once = self.0;
545                unsafe { deadlock::release_resource(core::ptr::from_ref(once).addr()) };
546                let state = once.0.swap(POISON_BIT, Ordering::Release);
547                if state & PARKED_BIT != 0 {
548                    let addr = core::ptr::from_ref(once).addr();
549                    unsafe {
550                        parking_lot_core::unpark_all(addr, DEFAULT_UNPARK_TOKEN);
551                    }
552                }
553            }
554        }
555
556        // At this point we have the lock, so record its ownership and run the
557        // closure. Make sure we properly clean up if the closure panics.
558        unsafe { deadlock::acquire_resource(core::ptr::from_ref(self).addr()) };
559        let guard = PanicGuard(self);
560        let once_state = if state & POISON_BIT != 0 {
561            OnceState::Poisoned
562        } else {
563            OnceState::New
564        };
565        f(once_state);
566        unsafe { deadlock::release_resource(core::ptr::from_ref(self).addr()) };
567        mem::forget(guard);
568
569        // Now unlock the state, set the done bit and unpark all threads
570        let state = self.0.swap(DONE_BIT, Ordering::Release);
571        if state & PARKED_BIT != 0 {
572            let addr = core::ptr::from_ref(self).addr();
573            unsafe {
574                parking_lot_core::unpark_all(addr, DEFAULT_UNPARK_TOKEN);
575            }
576        }
577    }
578}
579
580impl Default for Once {
581    #[inline]
582    fn default() -> Once {
583        Once::new()
584    }
585}
586
587impl fmt::Debug for Once {
588    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
589        f.debug_struct("Once")
590            .field("state", &self.state())
591            .finish()
592    }
593}
594
595#[cfg(test)]
596mod tests {
597    use super::PARKED_BIT;
598    use crate::Once;
599    use std::panic;
600    use std::sync::Arc;
601    use std::sync::atomic::{AtomicUsize, Ordering};
602    use std::sync::mpsc::channel;
603    use std::thread;
604
605    #[test]
606    fn smoke_once() {
607        static O: Once = Once::new();
608        let mut a = 0;
609        O.call_once(|| a += 1);
610        assert_eq!(a, 1);
611        O.call_once(|| a += 1);
612        assert_eq!(a, 1);
613    }
614
615    #[test]
616    fn wait_for_initialization() {
617        let once = Arc::new(Once::new());
618        let value = Arc::new(AtomicUsize::new(0));
619        let waiter = {
620            let once = Arc::clone(&once);
621            let value = Arc::clone(&value);
622            thread::spawn(move || {
623                once.wait();
624                assert_eq!(value.load(Ordering::Relaxed), 1);
625            })
626        };
627
628        while once.0.load(Ordering::Relaxed) & PARKED_BIT == 0 {
629            thread::yield_now();
630        }
631        once.call_once(|| value.store(1, Ordering::Relaxed));
632        waiter.join().unwrap();
633        assert!(once.is_completed());
634    }
635
636    #[test]
637    fn wait_propagates_poison() {
638        let once = Once::new();
639        assert!(panic::catch_unwind(|| once.call_once(|| panic!())).is_err());
640        assert!(panic::catch_unwind(|| once.wait()).is_err());
641    }
642
643    #[test]
644    fn wait_force_ignores_poison() {
645        let once = Arc::new(Once::new());
646        assert!(panic::catch_unwind(|| once.call_once(|| panic!())).is_err());
647
648        let waiter = {
649            let once = Arc::clone(&once);
650            thread::spawn(move || once.wait_force())
651        };
652        while once.0.load(Ordering::Relaxed) & PARKED_BIT == 0 {
653            thread::yield_now();
654        }
655        once.call_once_force(|state| assert!(state.is_poisoned()));
656        waiter.join().unwrap();
657        assert!(once.is_completed());
658    }
659
660    #[test]
661    fn stampede_once() {
662        static O: Once = Once::new();
663        static mut RUN: bool = false;
664
665        let (tx, rx) = channel();
666        for _ in 0..10 {
667            let tx = tx.clone();
668            thread::spawn(move || {
669                for _ in 0..4 {
670                    thread::yield_now()
671                }
672                unsafe {
673                    O.call_once(|| {
674                        assert!(!RUN);
675                        RUN = true;
676                    });
677                    assert!(RUN);
678                }
679                tx.send(()).unwrap();
680            });
681        }
682
683        unsafe {
684            O.call_once(|| {
685                assert!(!RUN);
686                RUN = true;
687            });
688            assert!(RUN);
689        }
690
691        for _ in 0..10 {
692            rx.recv().unwrap();
693        }
694    }
695
696    #[test]
697    fn poison_bad() {
698        static O: Once = Once::new();
699
700        // poison the once
701        let t = panic::catch_unwind(|| {
702            O.call_once(|| panic!());
703        });
704        assert!(t.is_err());
705
706        // poisoning propagates
707        let t = panic::catch_unwind(|| {
708            O.call_once(|| {});
709        });
710        assert!(t.is_err());
711
712        // we can subvert poisoning, however
713        let mut called = false;
714        O.call_once_force(|p| {
715            called = true;
716            assert!(p.poisoned())
717        });
718        assert!(called);
719
720        // once any success happens, we stop propagating the poison
721        O.call_once(|| {});
722    }
723
724    #[test]
725    fn wait_for_force_to_finish() {
726        static O: Once = Once::new();
727
728        // poison the once
729        let t = panic::catch_unwind(|| {
730            O.call_once(|| panic!());
731        });
732        assert!(t.is_err());
733
734        // make sure someone's waiting inside the once via a force
735        let (tx1, rx1) = channel();
736        let (tx2, rx2) = channel();
737        let t1 = thread::spawn(move || {
738            O.call_once_force(|p| {
739                assert!(p.poisoned());
740                tx1.send(()).unwrap();
741                rx2.recv().unwrap();
742            });
743        });
744
745        rx1.recv().unwrap();
746
747        // put another waiter on the once
748        let t2 = thread::spawn(|| {
749            let mut called = false;
750            O.call_once(|| {
751                called = true;
752            });
753            assert!(!called);
754        });
755
756        tx2.send(()).unwrap();
757
758        assert!(t1.join().is_ok());
759        assert!(t2.join().is_ok());
760    }
761
762    #[test]
763    fn test_once_debug() {
764        static O: Once = Once::new();
765
766        assert_eq!(format!("{:?}", O), "Once { state: New }");
767    }
768
769    #[test]
770    fn new_completed_is_done() {
771        use crate::OnceState;
772
773        static O: Once = Once::new_completed();
774        assert_eq!(O.state(), OnceState::Done);
775        assert!(O.state().done());
776        assert!(!O.state().poisoned());
777
778        let mut called = false;
779        O.call_once(|| called = true);
780        assert!(!called);
781        assert_eq!(O.state(), OnceState::Done);
782    }
783
784    #[test]
785    fn new_default_is_new() {
786        // Sanity check that the default constructor is unchanged.
787        static O: Once = Once::new();
788        let mut called = false;
789        O.call_once(|| called = true);
790        assert!(called);
791    }
792}