package http2
import (
)
var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
type goroutineLock uint64
func () goroutineLock {
if !DebugGoroutines {
return 0
}
return goroutineLock(curGoroutineID())
}
func ( goroutineLock) () {
if !DebugGoroutines {
return
}
if curGoroutineID() != uint64() {
panic("running on the wrong goroutine")
}
}
func ( goroutineLock) () {
if !DebugGoroutines {
return
}
if curGoroutineID() == uint64() {
panic("running on the wrong goroutine")
}
}
var goroutineSpace = []byte("goroutine ")
func () uint64 {
:= littleBuf.Get().(*[]byte)
defer littleBuf.Put()
:= *
= [:runtime.Stack(, false)]
= bytes.TrimPrefix(, goroutineSpace)
:= bytes.IndexByte(, ' ')
if < 0 {
panic(fmt.Sprintf("No space found in %q", ))
}
= [:]
, := parseUintBytes(, 10, 64)
if != nil {
panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", , ))
}
return
}
var littleBuf = sync.Pool{
New: func() interface{} {
:= make([]byte, 64)
return &
},
}
func ( []byte, int, int) ( uint64, error) {
var , uint64
if == 0 {
= int(strconv.IntSize)
}
:=
switch {
case len() < 1:
= strconv.ErrSyntax
goto
case 2 <= && <= 36:
case == 0:
switch {
case [0] == '0' && len() > 1 && ([1] == 'x' || [1] == 'X'):
= 16
= [2:]
if len() < 1 {
= strconv.ErrSyntax
goto
}
case [0] == '0':
= 8
default:
= 10
}
default:
= errors.New("invalid base " + strconv.Itoa())
goto
}
= 0
= cutoff64()
= 1<<uint() - 1
for := 0; < len(); ++ {
var byte
:= []
switch {
case '0' <= && <= '9':
= - '0'
case 'a' <= && <= 'z':
= - 'a' + 10
case 'A' <= && <= 'Z':
= - 'A' + 10
default:
= 0
= strconv.ErrSyntax
goto
}
if int() >= {
= 0
= strconv.ErrSyntax
goto
}
if >= {
= 1<<64 - 1
= strconv.ErrRange
goto
}
*= uint64()
:= + uint64()
if < || > {
= 1<<64 - 1
= strconv.ErrRange
goto
}
=
}
return , nil
:
return , &strconv.NumError{Func: "ParseUint", Num: string(), Err: }
}
func ( int) uint64 {
if < 2 {
return 0
}
return (1<<64-1)/uint64() + 1
}