@@ -221,13 +221,9 @@ impl Once {
221
221
/// [poison]: struct.Mutex.html#poisoning
222
222
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
223
223
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 ;
231
227
}
232
228
233
229
let mut f = Some ( f) ;
@@ -282,13 +278,9 @@ impl Once {
282
278
/// ```
283
279
#[ unstable( feature = "once_poison" , issue = "33577" ) ]
284
280
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 ;
292
284
}
293
285
294
286
let mut f = Some ( f) ;
@@ -297,6 +289,55 @@ impl Once {
297
289
} ) ;
298
290
}
299
291
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
+
300
341
// This is a non-generic function to reduce the monomorphization cost of
301
342
// using `call_once` (this isn't exactly a trivial or small implementation).
302
343
//
@@ -312,6 +353,10 @@ impl Once {
312
353
fn call_inner ( & self ,
313
354
ignore_poisoning : bool ,
314
355
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.
315
360
let mut state = self . state . load ( Ordering :: SeqCst ) ;
316
361
317
362
' outer: loop {
0 commit comments