1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
//! "一次初始化" 原语
//!
//! 该原语旨在用于运行一次性初始化。
//! 一个示例用例将是初始化 FFI 库。
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
use crate::fmt;
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::sys_common::once as sys;
/// 同步原语,可用于运行一次性初始化。
/// 对于 FFI 或相关功能的一次性初始化很有用。
/// 该类型只能用 [`Once::new()`] 构造。
///
/// # Examples
///
/// ```
/// use std::sync::Once;
///
/// static START: Once = Once::new();
///
/// START.call_once(|| {
/// // 在这里运行初始化
/// });
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Once {
inner: sys::Once,
}
#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")]
impl UnwindSafe for Once {}
#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")]
impl RefUnwindSafe for Once {}
/// 状态产生于 [`Once::call_once_force () `] 的闭包参数。
/// 该状态可用于查询 [`Once`] 的中毒状态。
#[stable(feature = "once_poison", since = "1.51.0")]
pub struct OnceState {
pub(crate) inner: sys::OnceState,
}
pub(crate) enum ExclusiveState {
Incomplete,
Poisoned,
Complete,
}
/// 静态 [`Once`] 值的初始化值。
///
/// # Examples
///
/// ```
/// use std::sync::{Once, ONCE_INIT};
///
/// static START: Once = ONCE_INIT;
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(
since = "1.38.0",
note = "the `new` function is now preferred",
suggestion = "Once::new()"
)]
pub const ONCE_INIT: Once = Once::new();
impl Once {
/// 创建一个新的 `Once` 值。
#[inline]
#[stable(feature = "once_new", since = "1.2.0")]
#[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
#[must_use]
pub const fn new() -> Once {
Once { inner: sys::Once::new() }
}
/// 仅执行一次初始化例程。如果这是第一次调用 `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 {
/// // ...
/// # 2
/// }
/// ```
///
/// # Panics
///
/// 如果在多个线程中同时调用闭包 `f`,则将仅执行一次。
/// 但是,如果该闭包 panics 将会毒化该 [`Once`] 实例,从而导致 `call_once` 的所有 future 调用也变为 panic。
///
/// 这类似于 [互斥体中毒][poison]。
///
/// [poison]: struct.Mutex.html#poisoning
///
///
///
///
///
///
///
///
///
///
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[track_caller]
pub fn call_once<F>(&self, f: F)
where
F: FnOnce(),
{
// 快速路径检查
if self.inner.is_completed() {
return;
}
let mut f = Some(f);
self.inner.call(false, &mut |_| f.take().unwrap()());
}
/// 执行与 [`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`] 的中毒状态。
///
/// [`call_once()`]: Once::call_once
/// [`call_once_force()`]: Once::call_once_force
///
/// # 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(|| {});
/// ```
///
///
///
///
///
#[inline]
#[stable(feature = "once_poison", since = "1.51.0")]
pub fn call_once_force<F>(&self, f: F)
where
F: FnOnce(&OnceState),
{
// 快速路径检查
if self.inner.is_completed() {
return;
}
let mut f = Some(f);
self.inner.call(true, &mut |p| f.take().unwrap()(p));
}
/// 如果某些 [`call_once()`] 调用已成功完成,则返回 `true`。具体而言,在以下情况下,`is_completed` 将返回 false:
/// * [`call_once()`] 根本没有被调用,
/// * [`call_once()`] 已被调用,但尚未完成,
/// * [`Once`] 实例中毒
///
/// 此函数返回 `false` 并不意味着 [`Once`] 尚未执行。
/// 例如,它可能是在 `is_completed` 开始执行到返回之间的时间执行的,在这种情况下,`false` 的返回值将是陈旧的 (但仍然是允许的)。
///
///
/// [`call_once()`]: Once::call_once
///
/// # 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);
/// ```
///
/// ```
/// 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);
/// ```
///
///
///
#[stable(feature = "once_is_completed", since = "1.43.0")]
#[inline]
pub fn is_completed(&self) -> bool {
self.inner.is_completed()
}
/// 返回 `Once` 实例的当前状态。
///
/// 由于这采用可变引用,因此当前无法运行任何初始化,因此状态必须是 "incomplete"、"poisoned" 或 "complete"。
///
///
#[inline]
pub(crate) fn state(&mut self) -> ExclusiveState {
self.inner.state()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Once {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Once").finish_non_exhaustive()
}
}
impl OnceState {
/// 如果关联的 [`Once`] 在调用传递给 [`Once::call_once_force()`] 的闭包之前中毒,则返回 `true`。
///
///
/// # Examples
///
/// 中毒的 [`Once`]:
///
/// ```
/// 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());
///
/// INIT.call_once_force(|state| {
/// assert!(state.is_poisoned());
/// });
/// ```
///
/// 无毒的 [`Once`]:
///
/// ```
/// use std::sync::Once;
///
/// static INIT: Once = Once::new();
///
/// INIT.call_once_force(|state| {
/// assert!(!state.is_poisoned());
/// });
#[stable(feature = "once_poison", since = "1.51.0")]
#[inline]
pub fn is_poisoned(&self) -> bool {
self.inner.is_poisoned()
}
/// 中毒关联的 [`Once`],而不显式 panic。
// NOTE: 这目前仅针对 `OnceLock` 公开。
#[inline]
pub(crate) fn poison(&self) {
self.inner.poison();
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for OnceState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OnceState").field("poisoned", &self.is_poisoned()).finish()
}
}