Update
This commit is contained in:
81
vendor/github.com/creachadair/msync/trigger/trigger.go
generated
vendored
Normal file
81
vendor/github.com/creachadair/msync/trigger/trigger.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
// Package trigger implements channel-based condition variable.
|
||||
package trigger
|
||||
|
||||
import "sync"
|
||||
|
||||
// A Cond is a condition shared by multiple goroutines. The [Cond.Ready]
|
||||
// method returns a channel that is closed when the condition is activated.
|
||||
//
|
||||
// When a condition is first created it is inactive. While inactive, reads on
|
||||
// the ready channel will block. The condition remains inactive until
|
||||
// [Cond.Set] or [Cond.Signal] is called, either of which causes the current
|
||||
// ready channel to be closed (and thus deliver a zero value). Once a condition
|
||||
// has been activated, it remains active until it is reset. Use [Cond.Reset] to
|
||||
// make it inactive again.
|
||||
//
|
||||
// The [Cond.Signal] method activates and then immediately resets the
|
||||
// condition, acting as Set and Reset done in a single step.
|
||||
//
|
||||
// A zero Cond is ready for use, and is inactive, but must not be copied after
|
||||
// any of its methods have been called.
|
||||
type Cond struct {
|
||||
μ sync.Mutex
|
||||
ch chan struct{}
|
||||
closed bool
|
||||
|
||||
// The signal channel is lazily initialized by the first waiter.
|
||||
}
|
||||
|
||||
// New constructs a new inactive [Cond].
|
||||
func New() *Cond { return new(Cond) }
|
||||
|
||||
// Signal activates and immediately resets the condition. If the condition was
|
||||
// already active, this is equivalent to [Cond.Reset].
|
||||
func (c *Cond) Signal() {
|
||||
c.μ.Lock()
|
||||
defer c.μ.Unlock()
|
||||
|
||||
if c.ch != nil && !c.closed {
|
||||
close(c.ch) // wake any pending waiters
|
||||
}
|
||||
c.ch = nil
|
||||
c.closed = false
|
||||
}
|
||||
|
||||
// Set activates the condition. If it was already active, Set has no effect.
|
||||
func (c *Cond) Set() {
|
||||
c.μ.Lock()
|
||||
defer c.μ.Unlock()
|
||||
|
||||
if c.ch == nil {
|
||||
c.ch = make(chan struct{})
|
||||
}
|
||||
if !c.closed {
|
||||
close(c.ch)
|
||||
c.closed = true
|
||||
}
|
||||
}
|
||||
|
||||
// Reset resets the condition. If it was already inactive, Reset has no effect.
|
||||
func (c *Cond) Reset() {
|
||||
c.μ.Lock()
|
||||
defer c.μ.Unlock()
|
||||
|
||||
if c.closed {
|
||||
c.ch = nil
|
||||
c.closed = false
|
||||
}
|
||||
}
|
||||
|
||||
// Ready returns a channel that is closed when c is activated. If c is active
|
||||
// when Ready is called, the returned channel will already be closed.
|
||||
func (c *Cond) Ready() <-chan struct{} {
|
||||
c.μ.Lock()
|
||||
defer c.μ.Unlock()
|
||||
|
||||
if c.ch == nil {
|
||||
c.ch = make(chan struct{})
|
||||
c.closed = false
|
||||
}
|
||||
return c.ch
|
||||
}
|
||||
Reference in New Issue
Block a user