Skip to content

Commit 8493813

Browse files
committed
Auto merge of #45429 - frewsxcv:frewsxcv-once-docs, r=quietmisdreavus
Improve docs around `Once::call_once_force` and `OnceState`. Added some examples, clarify behavior, etc etc. Fixes #43472.
2 parents 1babcd0 + aae94c7 commit 8493813

File tree

1 file changed

+81
-13
lines changed

1 file changed

+81
-13
lines changed

src/libstd/sync/once.rs

+81-13
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ unsafe impl Sync for Once {}
103103
#[stable(feature = "rust1", since = "1.0.0")]
104104
unsafe impl Send for Once {}
105105

106-
/// State yielded to the [`call_once_force`] method which can be used to query
107-
/// whether the [`Once`] was previously poisoned or not.
106+
/// State yielded to [`call_once_force`]’s closure parameter. The state can be
107+
/// used to query the poison status of the [`Once`].
108108
///
109109
/// [`call_once_force`]: struct.Once.html#method.call_once_force
110110
/// [`Once`]: struct.Once.html
@@ -230,17 +230,50 @@ impl Once {
230230

231231
/// Performs the same function as [`call_once`] except ignores poisoning.
232232
///
233+
/// Unlike [`call_once`], if this `Once` has been poisoned (i.e. a previous
234+
/// call to `call_once` or `call_once_force` caused a panic), calling
235+
/// `call_once_force` will still invoke the closure `f` and will _not_
236+
/// result in an immediate panic. If `f` panics, the `Once` will remain
237+
/// in a poison state. If `f` does _not_ panic, the `Once` will no
238+
/// longer be in a poison state and all future calls to `call_once` or
239+
/// `call_one_force` will no-op.
240+
///
241+
/// The closure `f` is yielded a [`OnceState`] structure which can be used
242+
/// to query the poison status of the `Once`.
243+
///
233244
/// [`call_once`]: struct.Once.html#method.call_once
245+
/// [`OnceState`]: struct.OnceState.html
234246
///
235-
/// If this `Once` has been poisoned (some initialization panicked) then
236-
/// this function will continue to attempt to call initialization functions
237-
/// until one of them doesn't panic.
247+
/// # Examples
238248
///
239-
/// The closure `f` is yielded a [`OnceState`] structure which can be used to query the
240-
/// state of this `Once` (whether initialization has previously panicked or
241-
/// not).
249+
/// ```
250+
/// #![feature(once_poison)]
242251
///
243-
/// [`OnceState`]: struct.OnceState.html
252+
/// use std::sync::{Once, ONCE_INIT};
253+
/// use std::thread;
254+
///
255+
/// static INIT: Once = ONCE_INIT;
256+
///
257+
/// // poison the once
258+
/// let handle = thread::spawn(|| {
259+
/// INIT.call_once(|| panic!());
260+
/// });
261+
/// assert!(handle.join().is_err());
262+
///
263+
/// // poisoning propagates
264+
/// let handle = thread::spawn(|| {
265+
/// INIT.call_once(|| {});
266+
/// });
267+
/// assert!(handle.join().is_err());
268+
///
269+
/// // call_once_force will still run and reset the poisoned state
270+
/// INIT.call_once_force(|state| {
271+
/// assert!(state.poisoned());
272+
/// });
273+
///
274+
/// // once any success happens, we stop propagating the poison
275+
/// INIT.call_once(|| {});
276+
/// ```
244277
#[unstable(feature = "once_poison", issue = "33577")]
245278
pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) {
246279
// same as above, just with a different parameter to `call_inner`.
@@ -386,12 +419,47 @@ impl Drop for Finish {
386419
}
387420

388421
impl OnceState {
389-
/// Returns whether the associated [`Once`] has been poisoned.
390-
///
391-
/// Once an initialization routine for a [`Once`] has panicked it will forever
392-
/// indicate to future forced initialization routines that it is poisoned.
422+
/// Returns whether the associated [`Once`] was poisoned prior to the
423+
/// invocation of the closure passed to [`call_once_force`].
393424
///
425+
/// [`call_once_force`]: struct.Once.html#method.call_once_force
394426
/// [`Once`]: struct.Once.html
427+
///
428+
/// # Examples
429+
///
430+
/// A poisoned `Once`:
431+
///
432+
/// ```
433+
/// #![feature(once_poison)]
434+
///
435+
/// use std::sync::{Once, ONCE_INIT};
436+
/// use std::thread;
437+
///
438+
/// static INIT: Once = ONCE_INIT;
439+
///
440+
/// // poison the once
441+
/// let handle = thread::spawn(|| {
442+
/// INIT.call_once(|| panic!());
443+
/// });
444+
/// assert!(handle.join().is_err());
445+
///
446+
/// INIT.call_once_force(|state| {
447+
/// assert!(state.poisoned());
448+
/// });
449+
/// ```
450+
///
451+
/// An unpoisoned `Once`:
452+
///
453+
/// ```
454+
/// #![feature(once_poison)]
455+
///
456+
/// use std::sync::{Once, ONCE_INIT};
457+
///
458+
/// static INIT: Once = ONCE_INIT;
459+
///
460+
/// INIT.call_once_force(|state| {
461+
/// assert!(!state.poisoned());
462+
/// });
395463
#[unstable(feature = "once_poison", issue = "33577")]
396464
pub fn poisoned(&self) -> bool {
397465
self.poisoned

0 commit comments

Comments
 (0)