-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathroutine_g.go
69 lines (60 loc) · 1.54 KB
/
routine_g.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
package routine
import (
"fmt"
"github.com/go-eden/routine/internal/g"
"reflect"
"runtime"
"sync/atomic"
"unsafe"
)
var (
goidOffset uintptr
labelsOffset uintptr
statusOffset uintptr
)
func init() {
offset := func(t reflect.Type, f string) uintptr {
if field, found := t.FieldByName(f); found {
return field.Offset
}
panic(fmt.Sprintf("init routine failed, cannot find g.%s, version=%s", f, runtime.Version()))
}
gt := reflect.TypeOf(g.G0())
goidOffset = offset(gt, "goid")
labelsOffset = offset(gt, "labels")
statusOffset = offset(gt, "atomicstatus")
}
type gAccessor struct {
ptr unsafe.Pointer
gid int64
}
func newGAccessor() *gAccessor {
return &gAccessor{
ptr: g.G(),
gid: Goid(),
}
}
func (g *gAccessor) Goid() int64 {
goidPtr := (*int64)(unsafe.Pointer(uintptr(g.ptr) + goidOffset))
return atomic.LoadInt64(goidPtr)
}
func (g *gAccessor) Labels() map[string]string {
labelsPPtr := (*unsafe.Pointer)(unsafe.Pointer(uintptr(g.ptr) + labelsOffset))
labelsPtr := atomic.LoadPointer(labelsPPtr)
if labelsPtr == nil {
return nil
}
// see SetGoroutineLabels, labelsPtr is `*labelMap`
return *(*map[string]string)(labelsPtr)
}
func (g *gAccessor) Status() GStatus {
if g.gid != g.Goid() {
return GDead
}
statusPtr := (*uint32)(unsafe.Pointer(uintptr(g.ptr) + statusOffset))
return GStatus(atomic.LoadUint32(statusPtr))
}
func (g *gAccessor) SetLabels(labels map[string]string) {
labelsPtr := (*unsafe.Pointer)(unsafe.Pointer(uintptr(g.ptr) + labelsOffset))
atomic.StorePointer(labelsPtr, unsafe.Pointer(&labels))
}