code: func (s *Sleeper) nextWaker(block bool) *Waker {
  	// Attempt to replenish the local list if it's currently empty.
  	if s.localList == nil {
  		for atomic.LoadPointer(&s.sharedList) == nil {
  			// Fail request if caller requested that we
  			// don't block.
  			if !block {
  				return nil
  			}
  
  			// Indicate to wakers that we're about to sleep,
  			// this allows them to abort the wait by setting
  			// waitingG back to zero (which we'll notice
  			// before committing the sleep).
  			atomic.StoreUintptr(&s.waitingG, preparingG)
  
  			// Check if something was queued while we were
  			// preparing to sleep. We need this interleaving
  			// to avoid missing wake ups.
  			if atomic.LoadPointer(&s.sharedList) != nil {
  				atomic.StoreUintptr(&s.waitingG, 0)
  				break
  			}
  
  			// Try to commit the sleep and report it to the
  			// tracer as a select.
  			//
  			// gopark puts the caller to sleep and calls
  			// commitSleep to decide whether to immediately
  			// wake the caller up or to leave it sleeping.
  			const traceEvGoBlockSelect = 24
  			gopark(commitSleep, &s.waitingG, "sleeper", traceEvGoBlockSelect, 0)
  		}
  
  		// Pull the shared list out and reverse it in the local
  		// list. Given that wakers push themselves in reverse
  		// order, we fix things here.
  		v := (*Waker)(atomic.SwapPointer(&s.sharedList, nil))
  		for v != nil {
  			cur := v
  			v = v.next
  
  			cur.next = s.localList
  			s.localList = cur
  		}
  	}
  
  	// Remove the waker in the front of the list.
  	w := s.localList
  	s.localList = w.next
  
  	return w
  }
docs: // nextWaker returns the next waker in the notification list, blocking if
  // needed.