-
Notifications
You must be signed in to change notification settings - Fork 0
/
thread.go
86 lines (70 loc) · 1.69 KB
/
thread.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
package thread
import (
"sync"
"context"
)
type ThreadGroup struct {
wait sync.WaitGroup
quit context.Context
cancel context.CancelFunc
}
type ThreadFuncCancel func(quit context.Context, cancel context.CancelFunc)
type ThreadFunc func()
func NewThreadGroup(parent context.Context) *ThreadGroup {
quit, cancel := context.WithCancel(parent)
out := &ThreadGroup{
quit: quit,
cancel: cancel,
}
return out
}
/* create a new group that can have its own set of threads.
* the current group will wait for all subgroups to exit
*/
func (group *ThreadGroup) SubGroup() *ThreadGroup {
out := NewThreadGroup(group.quit)
group.wait.Add(1)
go func(){
<-out.quit.Done()
out.wait.Wait()
defer group.wait.Done()
}()
return out
}
func (group *ThreadGroup) SpawnWithCancel(f ThreadFuncCancel){
group.wait.Add(1)
go func(){
defer group.wait.Done()
f(group.quit, group.cancel)
}()
}
func (group *ThreadGroup) Spawn(f ThreadFunc) {
group.wait.Add(1)
go func(){
defer group.wait.Done()
f()
}()
}
func (group *ThreadGroup) SpawnN(f ThreadFunc, i int) {
for n := 0; n < i; n++ {
group.Spawn(f)
}
}
func (group *ThreadGroup) Cancel(){
group.cancel()
}
func (group *ThreadGroup) Context() context.Context {
return group.quit
}
func (group *ThreadGroup) Done() <-chan struct{} {
return group.quit.Done()
}
func (group *ThreadGroup) Wait(){
group.wait.Wait()
// calling cancel here ensures the parent group will be notified about this group
group.cancel()
}
func (group *ThreadGroup) CancelAndWait() {
group.cancel()
group.wait.Wait()
}