ch3.8: 增加例子代码
This commit is contained in:
parent
4bc303bd53
commit
bbb1dea40f
|
@ -0,0 +1,5 @@
|
|||
package main
|
||||
|
||||
func main() {
|
||||
panic("goid")
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package main
|
||||
|
||||
import "runtime"
|
||||
|
||||
func main() {
|
||||
var buf = make([]byte, 64)
|
||||
var stk = buf[:runtime.Stack(buf, false)]
|
||||
println(string(stk))
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println("a:", GetGoid())
|
||||
go func() {
|
||||
println("b:", GetGoid())
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
func GetGoid() int64 {
|
||||
var (
|
||||
buf [64]byte
|
||||
n = runtime.Stack(buf[:], false)
|
||||
stk = strings.TrimPrefix(string(buf[:n]), "goroutine ")
|
||||
)
|
||||
|
||||
idField := strings.Fields(stk)[0]
|
||||
id, err := strconv.Atoi(idField)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can not get goroutine id: %v", err))
|
||||
}
|
||||
|
||||
return int64(id)
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func getg() unsafe.Pointer
|
||||
|
||||
const g_goid_offset = 152 // Go1.8/Go1.9/Go1.10/Go1.11/Go1.12/Go1.13
|
||||
|
||||
func GetGroutineId() int64 {
|
||||
g := getg()
|
||||
p := (*int64)(unsafe.Pointer(uintptr(g) + g_goid_offset))
|
||||
return *p
|
||||
}
|
||||
|
||||
func main() {
|
||||
println(GetGroutineId())
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#include "textflag.h"
|
||||
|
||||
// func getg() unsafe.Pointer
|
||||
TEXT ·getg(SB), NOSPLIT, $0-8
|
||||
MOVQ (TLS), AX
|
||||
MOVQ AX, ret+0(FP)
|
||||
RET
|
|
@ -0,0 +1,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
func getg() interface{}
|
||||
|
||||
type eface struct {
|
||||
_type, elem uintptr
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func runtime_convT2E_hack(_type, elem uintptr) eface {
|
||||
return eface{
|
||||
_type: _type,
|
||||
elem: elem,
|
||||
}
|
||||
}
|
||||
|
||||
func GetGoid() int64 {
|
||||
g := getg()
|
||||
goid := reflect.ValueOf(g).FieldByName("goid").Int()
|
||||
return goid
|
||||
}
|
||||
func main() {
|
||||
println("a:", GetGoid())
|
||||
go func() {
|
||||
println("b:", GetGoid())
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#include "textflag.h"
|
||||
|
||||
// func getg() interface{}
|
||||
TEXT ·getg(SB), NOSPLIT, $32-16
|
||||
// get runtime.g
|
||||
MOVQ (TLS), AX
|
||||
// get runtime.g type
|
||||
MOVQ $type·runtime·g(SB), BX
|
||||
|
||||
// convert (*g) to interface{}
|
||||
MOVQ AX, 8(SP)
|
||||
MOVQ BX, 0(SP)
|
||||
CALL ·runtime_convT2E_hack(SB)
|
||||
MOVQ 16(SP), AX
|
||||
MOVQ 24(SP), BX
|
||||
|
||||
// return interface{}
|
||||
MOVQ AX, ret+0(FP)
|
||||
MOVQ BX, ret+8(FP)
|
||||
RET
|
|
@ -0,0 +1,43 @@
|
|||
package gls
|
||||
|
||||
import "sync"
|
||||
|
||||
var gls struct {
|
||||
m map[int64]map[interface{}]interface{}
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func init() {
|
||||
gls.m = make(map[int64]map[interface{}]interface{})
|
||||
}
|
||||
|
||||
func getMap() map[interface{}]interface{} {
|
||||
gls.Lock()
|
||||
defer gls.Unlock()
|
||||
|
||||
goid := GetGoid()
|
||||
if m, _ := gls.m[goid]; m != nil {
|
||||
return m
|
||||
}
|
||||
|
||||
m := make(map[interface{}]interface{})
|
||||
gls.m[goid] = m
|
||||
return m
|
||||
}
|
||||
|
||||
func Get(key interface{}) interface{} {
|
||||
return getMap()[key]
|
||||
}
|
||||
func Put(key interface{}, v interface{}) {
|
||||
getMap()[key] = v
|
||||
}
|
||||
func Delete(key interface{}) {
|
||||
delete(getMap(), key)
|
||||
}
|
||||
|
||||
func Clean() {
|
||||
gls.Lock()
|
||||
defer gls.Unlock()
|
||||
|
||||
delete(gls.m, GetGoid())
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package gls
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func getg() interface{}
|
||||
|
||||
type eface struct {
|
||||
_type, elem uintptr
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func runtime_convT2E_hack(_type, elem uintptr) eface {
|
||||
return eface{
|
||||
_type: _type,
|
||||
elem: elem,
|
||||
}
|
||||
}
|
||||
|
||||
func GetGoid() int64 {
|
||||
g := getg()
|
||||
goid := reflect.ValueOf(g).FieldByName("goid").Int()
|
||||
return goid
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#include "textflag.h"
|
||||
|
||||
// func getg() interface{}
|
||||
TEXT ·getg(SB), NOSPLIT, $32-16
|
||||
// get runtime.g
|
||||
MOVQ (TLS), AX
|
||||
// get runtime.g type
|
||||
MOVQ $type·runtime·g(SB), BX
|
||||
|
||||
// convert (*g) to interface{}
|
||||
MOVQ AX, 8(SP)
|
||||
MOVQ BX, 0(SP)
|
||||
CALL ·runtime_convT2E_hack(SB)
|
||||
MOVQ 16(SP), AX
|
||||
MOVQ 24(SP), BX
|
||||
|
||||
// return interface{}
|
||||
MOVQ AX, ret+0(FP)
|
||||
MOVQ BX, ret+8(FP)
|
||||
RET
|
|
@ -0,0 +1,3 @@
|
|||
module gobook/ch3.8-6
|
||||
|
||||
go 1.13
|
|
@ -0,0 +1,25 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"gobook/ch3.8-6/gls"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 5; i++ {
|
||||
wg.Add(1)
|
||||
go func(idx int) {
|
||||
defer wg.Done()
|
||||
defer gls.Clean()
|
||||
|
||||
defer func() {
|
||||
fmt.Printf("%d: number = %d\n", idx, gls.Get("number"))
|
||||
}()
|
||||
gls.Put("number", idx+100)
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
Loading…
Reference in New Issue