@@ -78,9 +78,9 @@ use crate::thread::{self, Thread};
78
78
/// ```
79
79
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
80
80
pub struct Once {
81
- // This `state` word is actually an encoded version of just a pointer to a
82
- // `Waiter` , so we add the `PhantomData` appropriately.
83
- state : AtomicUsize ,
81
+ // `state_and_queue` is actually an a pointer to a `Waiter` with extra state
82
+ // bits , so we add the `PhantomData` appropriately.
83
+ state_and_queue : AtomicUsize ,
84
84
_marker : marker:: PhantomData < * mut Waiter > ,
85
85
}
86
86
@@ -121,8 +121,8 @@ pub struct OnceState {
121
121
) ]
122
122
pub const ONCE_INIT : Once = Once :: new ( ) ;
123
123
124
- // Four states that a Once can be in, encoded into the lower bits of `state` in
125
- // the Once structure.
124
+ // Four states that a Once can be in, encoded into the lower bits of
125
+ // `state_and_queue` in the Once structure.
126
126
const INCOMPLETE : usize = 0x0 ;
127
127
const POISONED : usize = 0x1 ;
128
128
const RUNNING : usize = 0x2 ;
@@ -151,7 +151,7 @@ impl Once {
151
151
#[ stable( feature = "once_new" , since = "1.2.0" ) ]
152
152
pub const fn new ( ) -> Once {
153
153
Once {
154
- state : AtomicUsize :: new ( INCOMPLETE ) ,
154
+ state_and_queue : AtomicUsize :: new ( INCOMPLETE ) ,
155
155
_marker : marker:: PhantomData ,
156
156
}
157
157
}
@@ -330,7 +330,7 @@ impl Once {
330
330
// operations visible to us, and, this being a fast path, weaker
331
331
// ordering helps with performance. This `Acquire` synchronizes with
332
332
// `SeqCst` operations on the slow path.
333
- self . state . load ( Ordering :: Acquire ) == COMPLETE
333
+ self . state_and_queue . load ( Ordering :: Acquire ) == COMPLETE
334
334
}
335
335
336
336
// This is a non-generic function to reduce the monomorphization cost of
@@ -352,10 +352,10 @@ impl Once {
352
352
// This cold path uses SeqCst consistently because the
353
353
// performance difference really does not matter there, and
354
354
// SeqCst minimizes the chances of something going wrong.
355
- let mut state = self . state . load ( Ordering :: SeqCst ) ;
355
+ let mut state_and_queue = self . state_and_queue . load ( Ordering :: SeqCst ) ;
356
356
357
357
' outer: loop {
358
- match state {
358
+ match state_and_queue {
359
359
// If we're complete, then there's nothing to do, we just
360
360
// jettison out as we shouldn't run the closure.
361
361
COMPLETE => return ,
@@ -372,10 +372,11 @@ impl Once {
372
372
// bits).
373
373
POISONED |
374
374
INCOMPLETE => {
375
- let old = self . state . compare_and_swap ( state, RUNNING ,
376
- Ordering :: SeqCst ) ;
377
- if old != state {
378
- state = old;
375
+ let old = self . state_and_queue . compare_and_swap ( state_and_queue,
376
+ RUNNING ,
377
+ Ordering :: SeqCst ) ;
378
+ if old != state_and_queue {
379
+ state_and_queue = old;
379
380
continue
380
381
}
381
382
@@ -388,7 +389,7 @@ impl Once {
388
389
panicked : true ,
389
390
me : self ,
390
391
} ;
391
- init ( state == POISONED ) ;
392
+ init ( state_and_queue == POISONED ) ;
392
393
complete. panicked = false ;
393
394
return
394
395
}
@@ -399,7 +400,7 @@ impl Once {
399
400
// head of the list and bail out if we ever see a state that's
400
401
// not RUNNING.
401
402
_ => {
402
- assert ! ( state & STATE_MASK == RUNNING ) ;
403
+ assert ! ( state_and_queue & STATE_MASK == RUNNING ) ;
403
404
let mut node = Waiter {
404
405
thread : Some ( thread:: current ( ) ) ,
405
406
signaled : AtomicBool :: new ( false ) ,
@@ -408,13 +409,13 @@ impl Once {
408
409
let me = & mut node as * mut Waiter as usize ;
409
410
assert ! ( me & STATE_MASK == 0 ) ;
410
411
411
- while state & STATE_MASK == RUNNING {
412
- node. next = ( state & !STATE_MASK ) as * mut Waiter ;
413
- let old = self . state . compare_and_swap ( state ,
414
- me | RUNNING ,
415
- Ordering :: SeqCst ) ;
416
- if old != state {
417
- state = old;
412
+ while state_and_queue & STATE_MASK == RUNNING {
413
+ node. next = ( state_and_queue & !STATE_MASK ) as * mut Waiter ;
414
+ let old = self . state_and_queue . compare_and_swap ( state_and_queue ,
415
+ me | RUNNING ,
416
+ Ordering :: SeqCst ) ;
417
+ if old != state_and_queue {
418
+ state_and_queue = old;
418
419
continue
419
420
}
420
421
@@ -424,7 +425,7 @@ impl Once {
424
425
while !node. signaled . load ( Ordering :: SeqCst ) {
425
426
thread:: park ( ) ;
426
427
}
427
- state = self . state . load ( Ordering :: SeqCst ) ;
428
+ state_and_queue = self . state_and_queue . load ( Ordering :: SeqCst ) ;
428
429
continue ' outer
429
430
}
430
431
}
@@ -444,19 +445,19 @@ impl Drop for Finish<'_> {
444
445
fn drop ( & mut self ) {
445
446
// Swap out our state with however we finished. We should only ever see
446
447
// an old state which was RUNNING.
447
- let queue = if self . panicked {
448
- self . me . state . swap ( POISONED , Ordering :: SeqCst )
448
+ let state_and_queue = if self . panicked {
449
+ self . me . state_and_queue . swap ( POISONED , Ordering :: SeqCst )
449
450
} else {
450
- self . me . state . swap ( COMPLETE , Ordering :: SeqCst )
451
+ self . me . state_and_queue . swap ( COMPLETE , Ordering :: SeqCst )
451
452
} ;
452
- assert_eq ! ( queue & STATE_MASK , RUNNING ) ;
453
+ assert_eq ! ( state_and_queue & STATE_MASK , RUNNING ) ;
453
454
454
455
// Decode the RUNNING to a list of waiters, then walk that entire list
455
456
// and wake them up. Note that it is crucial that after we store `true`
456
457
// in the node it can be free'd! As a result we load the `thread` to
457
458
// signal ahead of time and then unpark it after the store.
458
459
unsafe {
459
- let mut queue = ( queue & !STATE_MASK ) as * mut Waiter ;
460
+ let mut queue = ( state_and_queue & !STATE_MASK ) as * mut Waiter ;
460
461
while !queue. is_null ( ) {
461
462
let next = ( * queue) . next ;
462
463
let thread = ( * queue) . thread . take ( ) . unwrap ( ) ;
0 commit comments