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()
    }
}