Struct std::sync::Once

1.0.0 · source ·
pub struct Once { /* private fields */ }
Expand description

同步原语,可用于运行一次性初始化。 对于 FFI 或相关功能的一次性初始化很有用。 该类型只能用 Once::new() 构造。

Examples

use std::sync::Once;

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

START.call_once(|| {
    // 在这里运行初始化
});
Run

Implementations§

source§

impl Once

1.2.0 (const: 1.32.0) · source

pub const fn new() -> Once

创建一个新的 Once 值。

source

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

仅执行一次初始化例程。如果这是第一次调用 call_once,则将执行给定的闭包,否则将 调用例程。

如果当前正在运行另一个初始化例程,则此方法将阻止调用线程。

当这个函数返回时,保证一些初始化已经运行并完成 (它可能不是指定的闭包)。 还可以确保此时其他线程可以可靠地观察到由执行的闭包执行的任何内存写操作 (闭包与返回之后执行的代码之间存在先于发生的关系)。

如果给定的闭包在同一 Once 实例上递归调用 call_once,则未指定确切的行为,则允许的结果为 panic 或死锁。

Examples
use std::sync::Once;

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

// 在很多情况下,访问 `static mut` 是不安全的,但是如果我们以同步方式进行操作 (例如,一次写入或全部读取),那么我们就可以开始了!
// 此函数将只调用一次 `expensive_computation`,否则将始终返回从第一次调用返回的值。
fn get_cached_val() -> usize {
    unsafe {
        INIT.call_once(|| {
            VAL = expensive_computation();
        });
        VAL
    }
}

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

如果在多个线程中同时调用闭包 f,则将仅执行一次。 但是,如果该闭包 panics 将会毒化该 Once 实例,从而导致 call_once 的所有 future 调用也变为 panic。

这类似于 互斥体中毒

1.51.0 · source

pub fn call_once_force<F>(&self, f: F)where F: FnOnce(&OnceState),

执行与 call_once() 相同的函数,只是忽略中毒。

call_once() 不同,如果此 Once 已中毒 (例如,先前对 call_once()call_once_force() 的调用导致 panic),则调用 call_once_force() 仍将调用闭包 f,并且 not 会立即导致 panic。 如果 f panics,则 Once 将保持中毒状态。 如果 f 执行 not panic,则 Once 将不再处于中毒状态,并且所有对 call_once()call_once_force() 的 future 调用都将变为无操作。

闭包 f 产生 OnceState 结构体,可用于查询 Once 的中毒状态。

Examples
use std::sync::Once;
use std::thread;

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

// 中毒一次
let handle = thread::spawn(|| {
    INIT.call_once(|| panic!());
});
assert!(handle.join().is_err());

// 中毒传播
let handle = thread::spawn(|| {
    INIT.call_once(|| {});
});
assert!(handle.join().is_err());

// call_once_force 仍将运行并重置中毒状态
INIT.call_once_force(|state| {
    assert!(state.is_poisoned());
});

// 一旦成功,我们就停止传播毒药
INIT.call_once(|| {});
Run
1.43.0 · source

pub fn is_completed(&self) -> bool

如果某些 call_once() 调用已成功完成,则返回 true。具体而言,在以下情况下,is_completed 将返回 false:

此函数返回 false 并不意味着 Once 尚未执行。 例如,它可能是在 is_completed 开始执行到返回之间的时间执行的,在这种情况下,false 的返回值将是陈旧的 (但仍然是允许的)。

Examples
use std::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);
Run
use std::sync::Once;
use std::thread;

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

assert_eq!(INIT.is_completed(), false);
let handle = thread::spawn(|| {
    INIT.call_once(|| panic!());
});
assert!(handle.join().is_err());
assert_eq!(INIT.is_completed(), false);
Run

Trait Implementations§

1.16.0 · source§

impl Debug for Once

source§

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

使用给定的格式化程序格式化该值。 Read more
1.59.0 · source§

impl RefUnwindSafe for Once

1.59.0 · source§

impl UnwindSafe for Once

Auto Trait Implementations§

§

impl Send for Once

§

impl Sync for Once

§

impl Unpin for Once

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

获取 selfTypeIdRead more
source§

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

source§

fn borrow(&self) -> &T

从拥有的值中一成不变地借用。 Read more
source§

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

source§

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

从拥有的值中借用。 Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

返回未更改的参数。

source§

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

source§

fn into(self) -> U

调用 U::from(self)

也就是说,这种转换是 From<T> for U 实现选择执行的任何操作。

source§

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

§

type Error = Infallible

发生转换错误时返回的类型。
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

执行转换。
source§

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

§

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

发生转换错误时返回的类型。
source§

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

执行转换。