@@ -219,13 +219,9 @@ impl Once {
219
219
/// [poison]: struct.Mutex.html#poisoning
220
220
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
221
221
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 ;
229
225
}
230
226
231
227
let mut f = Some ( f) ;
@@ -280,13 +276,9 @@ impl Once {
280
276
/// ```
281
277
#[ unstable( feature = "once_poison" , issue = "33577" ) ]
282
278
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 ;
290
282
}
291
283
292
284
let mut f = Some ( f) ;
@@ -302,6 +294,10 @@ impl Once {
302
294
/// * `call_once` was called, but has not yet completed,
303
295
/// * the `Once` instance is poisoned
304
296
///
297
+ /// It is also possible that immediately after `is_completed`
298
+ /// returns false, some other thread finishes executing
299
+ /// `call_once`.
300
+ ///
305
301
/// # Examples
306
302
///
307
303
/// ```
@@ -333,6 +329,10 @@ impl Once {
333
329
/// ```
334
330
#[ unstable( feature = "once_is_completed" , issue = "42" ) ]
335
331
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.
336
336
self . state . load ( Ordering :: Acquire ) == COMPLETE
337
337
}
338
338
@@ -351,6 +351,10 @@ impl Once {
351
351
fn call_inner ( & self ,
352
352
ignore_poisoning : bool ,
353
353
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.
354
358
let mut state = self . state . load ( Ordering :: SeqCst ) ;
355
359
356
360
' outer: loop {
0 commit comments