type notifyList struct {
// wait is the ticket number of the next waiter. It is atomically
// incremented outside the lock.
- wait uint32
+ wait atomic.Uint32
// notify is the ticket number of the next waiter to be notified. It can
// be read outside the lock, but is only written to with lock held.
func notifyListAdd(l *notifyList) uint32 {
// This may be called concurrently, for example, when called from
// sync.Cond.Wait while holding a RWMutex in read mode.
- return atomic.Xadd(&l.wait, 1) - 1
+ return l.wait.Add(1) - 1
}
// notifyListWait waits for a notification. If one has been sent since
func notifyListNotifyAll(l *notifyList) {
// Fast-path: if there are no new waiters since the last notification
// we don't need to acquire the lock.
- if atomic.Load(&l.wait) == atomic.Load(&l.notify) {
+ if l.wait.Load() == atomic.Load(&l.notify) {
return
}
// value of wait because any previous waiters are already in the list
// or will notice that they have already been notified when trying to
// add themselves to the list.
- atomic.Store(&l.notify, atomic.Load(&l.wait))
+ atomic.Store(&l.notify, l.wait.Load())
unlock(&l.lock)
// Go through the local list and ready all waiters.
func notifyListNotifyOne(l *notifyList) {
// Fast-path: if there are no new waiters since the last notification
// we don't need to acquire the lock at all.
- if atomic.Load(&l.wait) == atomic.Load(&l.notify) {
+ if l.wait.Load() == atomic.Load(&l.notify) {
return
}
// Re-check under the lock if we need to do anything.
t := l.notify
- if t == atomic.Load(&l.wait) {
+ if t == l.wait.Load() {
unlock(&l.lock)
return
}