@@ -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