Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/util/trigger.go
4093 views
1
package util
2
3
import (
4
"context"
5
"sync"
6
"time"
7
8
"go.uber.org/atomic"
9
)
10
11
// WaitTrigger allows for waiting for a specific condition to be met.
12
// Useful for tests.
13
type WaitTrigger struct {
14
completed atomic.Bool
15
mut *sync.Mutex
16
cond *sync.Cond
17
}
18
19
// NewWaitTrigger creates a new WaitTrigger.
20
func NewWaitTrigger() *WaitTrigger {
21
var mut sync.Mutex
22
cond := sync.NewCond(&mut)
23
return &WaitTrigger{mut: &mut, cond: cond}
24
}
25
26
// Trigger completes the trigger and alerts all waiting. Calling Trigger again
27
// after the first invocation is a no-op.
28
func (wt *WaitTrigger) Trigger() {
29
wt.mut.Lock()
30
defer wt.mut.Unlock()
31
wt.completed.Store(true)
32
wt.cond.Broadcast()
33
}
34
35
// Wait waits for trigger to complete up to the specified timeout. Returns an
36
// error if the timeout expires.
37
func (wt *WaitTrigger) Wait(timeout time.Duration) error {
38
ctx, cancel := context.WithTimeout(context.Background(), timeout)
39
defer cancel()
40
return wt.WaitContext(ctx)
41
}
42
43
// WaitContext waits for trigger to complete or for the context to cancel.
44
// Returns an error if ctx gets canceled.
45
func (wt *WaitTrigger) WaitContext(ctx context.Context) error {
46
parentCtx := ctx
47
48
ctx, cancel := context.WithCancel(parentCtx)
49
defer cancel()
50
51
go func() {
52
<-ctx.Done()
53
54
// Ignore cancellations from our child context.
55
if parentCtx.Err() != nil {
56
wt.cond.Broadcast()
57
}
58
}()
59
60
wt.mut.Lock()
61
for ctx.Err() == nil && !wt.completed.Load() {
62
wt.cond.Wait()
63
}
64
err := parentCtx.Err()
65
wt.mut.Unlock()
66
return err
67
}
68
69