/
concurrency.go
107 lines (82 loc) · 1.73 KB
/
concurrency.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
96
97
98
99
100
101
102
103
104
105
106
107
package common
import (
"bytes"
"fmt"
"runtime"
"sort"
"strconv"
"sync"
"time"
)
type ErrTimeout struct {
Timeout time.Duration
Err error
}
func (e *ErrTimeout) Error() string {
return fmt.Sprintf("Timeout error after: %+v, error: %+v", e.Timeout, e.Err)
}
func NewTimeoutOperation(checkDuration time.Duration, maxDuration time.Duration, fn func() error) error {
start := time.Now()
err := fn()
if err == nil {
return nil
}
ti := time.NewTicker(checkDuration)
defer ti.Stop()
for {
<-ti.C
err := fn()
if err == nil {
return nil
}
if time.Since(start) > maxDuration {
return &ErrTimeout{maxDuration, err}
}
}
}
var (
routines = make(map[int]RuntimeInfo)
routinesCounter = 0
routinesMutex = sync.Mutex{}
)
func RegisterGoRoutine(index int) int {
routinesMutex.Lock()
defer routinesMutex.Unlock()
ri := GetRuntimeInfo(index)
id := routinesCounter
routinesCounter++
routines[id] = ri
return id
}
func UnregisterGoRoutine(id int) {
routinesMutex.Lock()
defer routinesMutex.Unlock()
delete(routines, id)
}
func RegisteredGoRoutines(f func(id int, ri RuntimeInfo)) {
routinesMutex.Lock()
defer routinesMutex.Unlock()
ks := make([]int, 0)
for k := range routines {
ks = append(ks, k)
}
sort.Ints(ks)
for _, k := range ks {
f(k, routines[k])
}
}
func GoRoutineId() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
func GoRoutineName() string {
buf := make([]byte, 100)
runtime.Stack(buf, true)
buf = bytes.Split(buf, []byte{'\n'})[0]
buf = buf[:len(buf)-1]
return string(bytes.TrimSuffix(buf, []byte("[running]")))
}