@@ -401,51 +401,55 @@ impl Once {
401401 // not RUNNING.
402402 _ => {
403403 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) ;
442405 state_and_queue = self . state_and_queue . load ( Ordering :: SeqCst ) ;
443406 }
444407 }
445408 }
446409 }
447410}
448411
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+
449453#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
450454impl fmt:: Debug for Once {
451455 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
0 commit comments