-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgraceful.go
75 lines (62 loc) · 1.69 KB
/
graceful.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
package graceful
import (
"os"
"os/signal"
"sync"
"syscall"
)
// Terminator is the interface that wraps the Terminate method.
//
// Terminate instructs the implementing object to shut down,
// close, disposes, or clean up any associated resources.
type Terminator interface {
Terminate()
}
// TerminatorFunc defines a type on func() as a convenience
type TerminatorFunc func()
// Terminate implements the Terminator interface on TerminatorFunc.
func (f TerminatorFunc) Terminate() {
f()
}
var (
tt []Terminator
mu = sync.Mutex{}
)
// In registers one or more Terminator(s) to execute in order.
func In(f ...Terminator) {
mu.Lock()
defer mu.Unlock()
tt = append(tt, f...)
}
var DefaultRunner = RoutineRunner{}
// Go is used to track go func()
func Go(f func()) {
DefaultRunner.Run(f)
}
var sig = make(chan os.Signal, 1)
// DefaultWaitSignals a list of os.Signals to be notified on for the Wait operation.
var DefaultWaitSignals = []os.Signal{syscall.SIGINT, syscall.SIGTERM}
// Wait listens for the provided notification signals from the os.
// When the signal is received, all registered terminators are
// executed in sequence.
//
// When the sigs argument is omitted, we wait on the signals defined
// in DefaultWaitSignals. Finally, tracked go routines are terminated
// last if they are not registered for termination using In.
func Wait(sigs ...os.Signal) {
if len(sigs) == 0 {
sigs = append(sigs, DefaultWaitSignals...)
}
signal.Notify(sig, sigs...)
<-sig
didTerminateRoutines := false
for _, t := range tt {
if _, ok := t.(*RoutineRunner); ok && !didTerminateRoutines {
didTerminateRoutines = true
}
t.Terminate()
}
if !didTerminateRoutines {
GoRoutineTerminator().Terminate()
}
}