github.com/suiyunonghen/DxCommonLib@v0.5.3/system/goid.go (about) 1 //from: https://github.com/rpccloud/goid 2 3 package system 4 5 import ( 6 "github.com/suiyunonghen/DxCommonLib" 7 "runtime" 8 "strings" 9 "sync" 10 "sync/atomic" 11 "unsafe" 12 ) 13 14 func getg() unsafe.Pointer 15 16 var ( 17 goroutinePrefix = "goroutine " 18 gidPos = getGidPos() 19 ) 20 21 func slowID() int64 { 22 buf := [32]byte{} 23 24 // Parse the 4707 out of "goroutine 4707 [" 25 str := strings.TrimPrefix( 26 string(buf[:runtime.Stack(buf[:], false)]), 27 goroutinePrefix, 28 ) 29 30 if lastPos := strings.IndexByte(str, ' '); lastPos > 0 { 31 if id, err := DxCommonLib.ParseInt64(str[:lastPos]); err == nil { 32 return id 33 } 34 } 35 return 0 36 } 37 38 var getGidPos = func() func() int { 39 fnFindGidPos := func(start int) int { 40 if currGID, ptr := slowID(), getg(); currGID > 0 && uintptr(ptr) > 0 { 41 pos := start 42 for pos < 4096 { 43 if *(*int64)(unsafe.Pointer(uintptr(ptr) + uintptr(pos))) == currGID { 44 return pos 45 } 46 pos++ 47 } 48 } 49 return -1 50 } 51 52 fnCheckPos := func(pos int) bool { 53 var wg sync.WaitGroup 54 checkCount := int32(32) 55 wg.Add(int(checkCount)) 56 checkIndex := int32(0) 57 for i := 0; i < int(checkCount); i++ { 58 DxCommonLib.PostFunc(func(data ...interface{}) { 59 if fnFindGidPos(pos) == pos { 60 atomic.AddInt32(&checkIndex,1) 61 } 62 wg.Done() 63 }) 64 } 65 wg.Wait() 66 return atomic.LoadInt32(&checkIndex) == checkCount 67 } 68 69 return func() int { 70 pos := fnFindGidPos(0) 71 for pos != -1 { 72 if fnCheckPos(pos) { 73 break 74 } else { 75 pos = fnFindGidPos(pos + 1) 76 } 77 } 78 return pos 79 } 80 }() 81 82 // GetRoutineId get current goroutine id 83 func GetRoutineId() int64 { 84 if gidPos >= 0 { 85 return *(*int64)(unsafe.Pointer(uintptr(getg()) + uintptr(gidPos))) 86 } 87 88 return slowID() 89 }