-
Notifications
You must be signed in to change notification settings - Fork 1
/
stopper.go
95 lines (84 loc) · 2.26 KB
/
stopper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package stop
import (
"sync"
)
// Stopper is an interface for objects that can be used with Group. See
// ChannelStopper for a simple implementation using channels.
//
// IsStopping should return true if Stop has been called.
//
// IsStopped should return a true if Stopped has been called.
//
// Stop should be a non-blocking notification to stop any work in progress.
// It should be safe to call this multiple times.
//
// Stopped should be a non-blocking notification that work has been stopped.
// It should be safe to call this multiple times.
//
// WaitForStopped should block until the work has been stopped.
type Stopper interface {
IsStopping() bool
IsStopped() bool
Stop()
StopChannel() chan bool
Stopped()
StoppedChannel() chan bool
WaitForStopped()
}
// ChannelStopper is an implementation of Stopper using channels.
type ChannelStopper struct {
stop chan bool
stopped chan bool
mutex sync.RWMutex
isStopped bool
isStopping bool
}
// NewChannelStopper returns a new ChannelStopper.
func NewChannelStopper() *ChannelStopper {
return &ChannelStopper{
stop: make(chan bool),
stopped: make(chan bool),
}
}
// IsStopped returns true if Stopped has been called.
func (s *ChannelStopper) IsStopped() bool {
s.mutex.RLock()
defer s.mutex.RUnlock()
return s.isStopped
}
// IsStopping returns true if Stop has been called.
func (s *ChannelStopper) IsStopping() bool {
s.mutex.RLock()
defer s.mutex.RUnlock()
return s.isStopping
}
// Stop notifies that work should stop by closing the stop channel.
func (s *ChannelStopper) Stop() {
s.mutex.Lock()
defer s.mutex.Unlock()
if !s.isStopping {
close(s.stop)
s.isStopping = true
}
}
// StopChannel returns a channel that will be closed when Stop is called.
func (s *ChannelStopper) StopChannel() chan bool {
return s.stop
}
// Stopped notifies that work has stopped by closing the stopped channel.
func (s *ChannelStopper) Stopped() {
s.mutex.Lock()
defer s.mutex.Unlock()
if !s.isStopped {
close(s.stopped)
s.isStopped = true
}
}
// StoppedChannel returns a channel that will be closed when Stopped is called.
func (s *ChannelStopper) StoppedChannel() chan bool {
return s.stopped
}
// WaitForStopped blocks until Stopped is called.
func (s *ChannelStopper) WaitForStopped() {
<-s.stopped
}