github.com/GoWebProd/gip@v0.0.0-20230623090727-b60d41d5d320/cond/multi.go (about)

     1  package cond
     2  
     3  import (
     4  	"sync"
     5  	"unsafe"
     6  
     7  	"github.com/GoWebProd/gip/rtime"
     8  	"github.com/GoWebProd/gip/stack"
     9  )
    10  
    11  type Multi struct {
    12  	ready   bool
    13  	waiters stack.MutexStack[unsafe.Pointer]
    14  	mu      sync.Mutex
    15  }
    16  
    17  func (c *Multi) park(p1, p2 unsafe.Pointer) bool {
    18  	c.waiters.PushUnlocked(p1)
    19  	c.mu.Unlock()
    20  
    21  	return true
    22  }
    23  
    24  func (c *Multi) Wait() {
    25  	c.mu.Lock()
    26  
    27  	if c.ready {
    28  		c.mu.Unlock()
    29  
    30  		return
    31  	}
    32  
    33  	rtime.GoPark(c.park, unsafe.Pointer(&c.mu), 0, 0, 1)
    34  }
    35  
    36  func (c *Multi) Done() {
    37  	c.mu.Lock()
    38  
    39  	c.ready = true
    40  
    41  	for {
    42  		g, ok := c.waiters.PopUnlocked()
    43  		if !ok {
    44  			break
    45  		}
    46  
    47  		rtime.GoReady(g, 1)
    48  	}
    49  
    50  	c.mu.Unlock()
    51  }