github.com/sandwich-go/boost@v1.3.29/xsync/cond.go (about)

     1  package xsync
     2  
     3  import (
     4  	"sync"
     5  )
     6  
     7  // Cond is an alternate implementation of sync.Cond
     8  type Cond struct {
     9  	L       sync.Locker
    10  	sema    chan struct{}
    11  	waiters AtomicInt64
    12  }
    13  
    14  func NewCond(l sync.Locker) *Cond {
    15  	return &Cond{L: l, sema: make(chan struct{})}
    16  }
    17  
    18  func (c *Cond) Wait() {
    19  	c.waiters.Add(1)
    20  	c.L.Unlock()
    21  	<-c.sema
    22  	c.L.Lock()
    23  }
    24  
    25  func (c *Cond) Signal() {
    26  	for {
    27  		w := c.waiters.Get()
    28  		if w == 0 {
    29  			return
    30  		}
    31  		if c.waiters.CompareAndSwap(w, w-1) {
    32  			break
    33  		}
    34  	}
    35  	c.sema <- struct{}{}
    36  }
    37  
    38  func (c *Cond) Broadcast() {
    39  	var w int64
    40  	for {
    41  		w = c.waiters.Get()
    42  		if w == 0 {
    43  			return
    44  		}
    45  		if c.waiters.CompareAndSwap(w, 0) {
    46  			break
    47  		}
    48  	}
    49  	for i := int64(0); i < w; i++ {
    50  		c.sema <- struct{}{}
    51  	}
    52  }