@@ -401,51 +401,55 @@ impl Once {
401
401
// not RUNNING.
402
402
_ => {
403
403
assert ! ( state_and_queue & STATE_MASK == RUNNING ) ;
404
- // Create the node for our current thread that we are going to try to slot
405
- // in at the head of the linked list.
406
- let mut node = Waiter {
407
- thread : thread:: current ( ) ,
408
- signaled : AtomicBool :: new ( false ) ,
409
- next : ptr:: null ( ) ,
410
- } ;
411
- let me = & node as * const Waiter as usize ;
412
- assert ! ( me & STATE_MASK == 0 ) ; // We assume pointers have 2 free bits that
413
- // we can use for state.
414
-
415
- // Try to slide in the node at the head of the linked list.
416
- // Run in a loop where we make sure the status is still RUNNING, and that
417
- // another thread did not just replace the head of the linked list.
418
- let mut old_head_and_status = state_and_queue;
419
- loop {
420
- if old_head_and_status & STATE_MASK != RUNNING {
421
- return ; // No need anymore to enqueue ourselves.
422
- }
423
-
424
- node. next = ( old_head_and_status & !STATE_MASK ) as * const Waiter ;
425
- let old = self . state_and_queue . compare_and_swap ( old_head_and_status,
426
- me | RUNNING ,
427
- Ordering :: Release ) ;
428
- if old == old_head_and_status {
429
- break ; // Success!
430
- }
431
- old_head_and_status = old;
432
- }
433
-
434
- // We have enqueued ourselves, now lets wait.
435
- // It is important not to return before being signaled, otherwise we would
436
- // drop our `Waiter` node and leave a hole in the linked list (and a
437
- // dangling reference). Guard against spurious wakeups by reparking
438
- // ourselves until we are signaled.
439
- while !node. signaled . load ( Ordering :: SeqCst ) {
440
- thread:: park ( ) ;
441
- }
404
+ wait ( & self . state_and_queue , state_and_queue) ;
442
405
state_and_queue = self . state_and_queue . load ( Ordering :: SeqCst ) ;
443
406
}
444
407
}
445
408
}
446
409
}
447
410
}
448
411
412
+ fn wait ( state_and_queue : & AtomicUsize , current_state : usize ) {
413
+ // Create the node for our current thread that we are going to try to slot
414
+ // in at the head of the linked list.
415
+ let mut node = Waiter {
416
+ thread : thread:: current ( ) ,
417
+ signaled : AtomicBool :: new ( false ) ,
418
+ next : ptr:: null ( ) ,
419
+ } ;
420
+ let me = & node as * const Waiter as usize ;
421
+ assert ! ( me & STATE_MASK == 0 ) ; // We assume pointers have 2 free bits that
422
+ // we can use for state.
423
+
424
+ // Try to slide in the node at the head of the linked list.
425
+ // Run in a loop where we make sure the status is still RUNNING, and that
426
+ // another thread did not just replace the head of the linked list.
427
+ let mut old_head_and_status = current_state;
428
+ loop {
429
+ if old_head_and_status & STATE_MASK != RUNNING {
430
+ return ; // No need anymore to enqueue ourselves.
431
+ }
432
+
433
+ node. next = ( old_head_and_status & !STATE_MASK ) as * const Waiter ;
434
+ let old = state_and_queue. compare_and_swap ( old_head_and_status,
435
+ me | RUNNING ,
436
+ Ordering :: Release ) ;
437
+ if old == old_head_and_status {
438
+ break ; // Success!
439
+ }
440
+ old_head_and_status = old;
441
+ }
442
+
443
+ // We have enqueued ourselves, now lets wait.
444
+ // It is important not to return before being signaled, otherwise we would
445
+ // drop our `Waiter` node and leave a hole in the linked list (and a
446
+ // dangling reference). Guard against spurious wakeups by reparking
447
+ // ourselves until we are signaled.
448
+ while !node. signaled . load ( Ordering :: SeqCst ) {
449
+ thread:: park ( ) ;
450
+ }
451
+ }
452
+
449
453
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
450
454
impl fmt:: Debug for Once {
451
455
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
0 commit comments