Skip to main content

Once

Struct Once 

Source
pub struct Once(/* private fields */);
Available on crate feature full and non-crate feature use_std only.
Expand description

A low-level synchronization primitive for one-time global execution.

§Examples

use kernel_api::sync::Once;

static START: Once = Once::new();

START.call_once(|| {
    // run initialization here
});

Implementations§

Source§

impl Once

Source

pub const fn new() -> Self

Creates a new Once value.

Source

pub fn call_once<F: FnOnce()>(&self, f: F)

Performs an initialization routine once and only once. The given closure will be executed if this is the first time call_once has been called, and otherwise the routine will not be invoked.

This method will spin if another initialization routine is currently running.

When this function returns, it is guaranteed that some initialization has run and completed (it might not be the closure specified). It is also guaranteed that any memory writes performed by the executed closure can be reliably observed by other threads at this point (there is a happens-before relation between the closure and code executing after the return).

If the given closure recursively invokes call_once on the same Once instance, the exact behavior is not specified: allowed outcomes are a panic or a deadlock.

§Examples
use kernel_api::sync::Once;

static mut VAL: usize = 0;
static INIT: Once = Once::new();

// Accessing a `static mut` is unsafe much of the time, but if we do so
// in a synchronized fashion (e.g., write once or read all) then we're
// good to go!
//
// This function will only call `expensive_computation` once, and will
// otherwise always return the value returned from the first invocation.
fn get_cached_val() -> usize {
    unsafe {
        INIT.call_once(|| {
            VAL = expensive_computation();
        });
        VAL
    }
}

fn expensive_computation() -> usize {
    // ...
}
§Panics

The closure f will only be executed once even if this is called concurrently amongst many threads. If that closure panics, however, then it will poison this Once instance, causing all future invocations of call_once to also panic.

Source

pub fn is_complete(&self) -> bool

Returns true if some [call_once()] call has completed successfully. Specifically, is_completed will return false in the following situations:

  • [call_once()] was not called at all,
  • [call_once()] was called, but has not yet completed,
  • the Once instance is poisoned

This function returning false does not mean that Once has not been executed. For example, it may have been executed in the time between when is_completed starts executing and when it returns, in which case the false return value would be stale (but still permissible).

§Panics

If this Once is poisoned due to the closure passed to [call_once] panicking.

§Examples
use kernel_api::sync::Once;

static INIT: Once = Once::new();

assert_eq!(INIT.is_completed(), false);
INIT.call_once(|| {
    assert_eq!(INIT.is_completed(), false);
});
assert_eq!(INIT.is_completed(), true);

Trait Implementations§

Source§

impl Debug for Once

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Once

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl !Freeze for Once

§

impl RefUnwindSafe for Once

§

impl Send for Once

§

impl Sync for Once

§

impl Unpin for Once

§

impl UnsafeUnpin for Once

§

impl UnwindSafe for Once

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = !

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.