@@ -221,13 +221,9 @@ impl Once {
221221 /// [poison]: struct.Mutex.html#poisoning
222222 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
223223 pub fn call_once < F > ( & self , f : F ) where F : FnOnce ( ) {
224- // Fast path, just see if we've completed initialization.
225- // An `Acquire` load is enough because that makes all the initialization
226- // operations visible to us. The cold path uses SeqCst consistently
227- // because the performance difference really does not matter there,
228- // and SeqCst minimizes the chances of something going wrong.
229- if self . state . load ( Ordering :: Acquire ) == COMPLETE {
230- return
224+ // Fast path check
225+ if self . is_completed ( ) {
226+ return ;
231227 }
232228
233229 let mut f = Some ( f) ;
@@ -282,13 +278,9 @@ impl Once {
282278 /// ```
283279 #[ unstable( feature = "once_poison" , issue = "33577" ) ]
284280 pub fn call_once_force < F > ( & self , f : F ) where F : FnOnce ( & OnceState ) {
285- // same as above, just with a different parameter to `call_inner`.
286- // An `Acquire` load is enough because that makes all the initialization
287- // operations visible to us. The cold path uses SeqCst consistently
288- // because the performance difference really does not matter there,
289- // and SeqCst minimizes the chances of something going wrong.
290- if self . state . load ( Ordering :: Acquire ) == COMPLETE {
291- return
281+ // Fast path check
282+ if self . is_completed ( ) {
283+ return ;
292284 }
293285
294286 let mut f = Some ( f) ;
@@ -297,6 +289,55 @@ impl Once {
297289 } ) ;
298290 }
299291
292+ /// Returns true if some `call_once` call has completed
293+ /// successfuly. Specifically, `is_completed` will return false in
294+ /// the following situtations:
295+ /// * `call_once` was not called at all,
296+ /// * `call_once` was called, but has not yet completed,
297+ /// * the `Once` instance is poisoned
298+ ///
299+ /// It is also possible that immediately after `is_completed`
300+ /// returns false, some other thread finishes executing
301+ /// `call_once`.
302+ ///
303+ /// # Examples
304+ ///
305+ /// ```
306+ /// #![feature(once_is_completed)]
307+ /// use std::sync::Once;
308+ ///
309+ /// static INIT: Once = Once::new();
310+ ///
311+ /// assert_eq!(INIT.is_completed(), false);
312+ /// INIT.call_once(|| {
313+ /// assert_eq!(INIT.is_completed(), false);
314+ /// });
315+ /// assert_eq!(INIT.is_completed(), true);
316+ /// ```
317+ ///
318+ /// ```
319+ /// #![feature(once_is_completed)]
320+ /// use std::sync::Once;
321+ /// use std::thread;
322+ ///
323+ /// static INIT: Once = Once::new();
324+ ///
325+ /// assert_eq!(INIT.is_completed(), false);
326+ /// let handle = thread::spawn(|| {
327+ /// INIT.call_once(|| panic!());
328+ /// });
329+ /// assert!(handle.join().is_err());
330+ /// assert_eq!(INIT.is_completed(), false);
331+ /// ```
332+ #[ unstable( feature = "once_is_completed" , issue = "42" ) ]
333+ pub fn is_completed ( & self ) -> bool {
334+ // An `Acquire` load is enough because that makes all the initialization
335+ // operations visible to us, and, this being a fast path, weaker
336+ // ordering helps with performance. This `Acquire` synchronizes with
337+ // `SeqCst` operations on the slow path.
338+ self . state . load ( Ordering :: Acquire ) == COMPLETE
339+ }
340+
300341 // This is a non-generic function to reduce the monomorphization cost of
301342 // using `call_once` (this isn't exactly a trivial or small implementation).
302343 //
@@ -312,6 +353,10 @@ impl Once {
312353 fn call_inner ( & self ,
313354 ignore_poisoning : bool ,
314355 init : & mut dyn FnMut ( bool ) ) {
356+
357+ // This cold path uses SeqCst consistently because the
358+ // performance difference really does not matter there, and
359+ // SeqCst minimizes the chances of something going wrong.
315360 let mut state = self . state . load ( Ordering :: SeqCst ) ;
316361
317362 ' outer: loop {
0 commit comments