-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecutor.go
More file actions
86 lines (74 loc) · 1.4 KB
/
Copy pathexecutor.go
File metadata and controls
86 lines (74 loc) · 1.4 KB
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 executor
import (
"context"
"sync"
)
const (
defaultNumOfGoroutines = 10
)
type WorkerService struct {
ctx context.Context
pool chan *worker
workersNum int
start *sync.Once
stop *sync.Once
exit chan struct{}
}
func NewService(ctx context.Context, workerNums int) WorkerPool {
if workerNums <= 0 {
workerNums = defaultNumOfGoroutines
}
return &WorkerService{
ctx: ctx,
pool: make(chan *worker, workerNums),
workersNum: workerNums,
start: &sync.Once{},
stop: &sync.Once{},
exit: make(chan struct{}),
}
}
func (s *WorkerService) Start() {
s.start.Do(func() {
for i := 0; i < s.workersNum; i++ {
s.pool <- newWorker(i + 1)
}
})
}
func (s *WorkerService) Stop() {
s.stop.Do(func() {
close(s.exit)
})
}
func (s *WorkerService) AddTasks(tasks ...Runnable) {
for i := 0; i < len(tasks); i++ {
select {
case <-s.ctx.Done():
return
case <-s.exit:
return
case w := <-s.pool:
go s.process(w, tasks[i])
}
}
}
func (s *WorkerService) process(w *worker, task Runnable) {
select {
case <-s.ctx.Done():
return
case <-s.exit:
return
default:
defer s.backWorkerToPool(w)
if err := task.Execute(); err != nil {
task.OnError(err)
return
}
if err := task.OnComplete(); err != nil {
task.OnError(err)
return
}
}
}
func (s *WorkerService) backWorkerToPool(w *worker) {
s.pool <- w
}