Skip to content

Commit e1bd0e7

Browse files
committed
Reduce code duplication in Once
1 parent 6aba6f9 commit e1bd0e7

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

src/libstd/sync/once.rs

+18-14
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,9 @@ impl Once {
219219
/// [poison]: struct.Mutex.html#poisoning
220220
#[stable(feature = "rust1", since = "1.0.0")]
221221
pub fn call_once<F>(&self, f: F) where F: FnOnce() {
222-
// Fast path, just see if we've completed initialization.
223-
// An `Acquire` load is enough because that makes all the initialization
224-
// operations visible to us. The cold path uses SeqCst consistently
225-
// because the performance difference really does not matter there,
226-
// and SeqCst minimizes the chances of something going wrong.
227-
if self.state.load(Ordering::Acquire) == COMPLETE {
228-
return
222+
// Fast path check
223+
if self.is_completed() {
224+
return;
229225
}
230226

231227
let mut f = Some(f);
@@ -280,13 +276,9 @@ impl Once {
280276
/// ```
281277
#[unstable(feature = "once_poison", issue = "33577")]
282278
pub fn call_once_force<F>(&self, f: F) where F: FnOnce(&OnceState) {
283-
// same as above, just with a different parameter to `call_inner`.
284-
// An `Acquire` load is enough because that makes all the initialization
285-
// operations visible to us. The cold path uses SeqCst consistently
286-
// because the performance difference really does not matter there,
287-
// and SeqCst minimizes the chances of something going wrong.
288-
if self.state.load(Ordering::Acquire) == COMPLETE {
289-
return
279+
// Fast path check
280+
if self.is_completed() {
281+
return;
290282
}
291283

292284
let mut f = Some(f);
@@ -302,6 +294,10 @@ impl Once {
302294
/// * `call_once` was called, but has not yet completed,
303295
/// * the `Once` instance is poisoned
304296
///
297+
/// It is also possible that immediately after `is_completed`
298+
/// returns false, some other thread finishes executing
299+
/// `call_once`.
300+
///
305301
/// # Examples
306302
///
307303
/// ```
@@ -333,6 +329,10 @@ impl Once {
333329
/// ```
334330
#[unstable(feature = "once_is_completed", issue = "42")]
335331
pub fn is_completed(&self) -> bool {
332+
// An `Acquire` load is enough because that makes all the initialization
333+
// operations visible to us, and, this being a fast path, weaker
334+
// ordering helps with performance. This `Acquire` synchronizes with
335+
// `SeqCst` operations on the slow path.
336336
self.state.load(Ordering::Acquire) == COMPLETE
337337
}
338338

@@ -351,6 +351,10 @@ impl Once {
351351
fn call_inner(&self,
352352
ignore_poisoning: bool,
353353
init: &mut dyn FnMut(bool)) {
354+
355+
// This cold path uses SeqCst consistently because the
356+
// performance difference really does not matter there, and
357+
// SeqCst minimizes the chances of something going wrong.
354358
let mut state = self.state.load(Ordering::SeqCst);
355359

356360
'outer: loop {

0 commit comments

Comments
 (0)