// Copyright 2014 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// Defensive debug-only utility to track that functions run on the// goroutine that they're supposed to.package http2import ()varDebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"// Setting DebugGoroutines to false during a test to disable goroutine debugging// results in race detector complaints when a test leaves goroutines running before// returning. Tests shouldn't do this, of course, but when they do it generally shows// up as infrequent, hard-to-debug flakes. (See #66519.)//// Disable goroutine debugging during individual tests with an atomic bool.// (Note that it's safe to enable/disable debugging mid-test, so the actual race condition// here is harmless.)var disableDebugGoroutines atomic.Booltype goroutineLock uint64func newGoroutineLock() goroutineLock {if !DebugGoroutines || disableDebugGoroutines.Load() {return0 }returngoroutineLock(curGoroutineID())}func ( goroutineLock) () {if !DebugGoroutines || disableDebugGoroutines.Load() {return }ifcurGoroutineID() != uint64() {panic("running on the wrong goroutine") }}func ( goroutineLock) () {if !DebugGoroutines || disableDebugGoroutines.Load() {return }ifcurGoroutineID() == uint64() {panic("running on the wrong goroutine") }}var goroutineSpace = []byte("goroutine ")func curGoroutineID() uint64 { := littleBuf.Get().(*[]byte)deferlittleBuf.Put() := * = [:runtime.Stack(, false)]// Parse the 4707 out of "goroutine 4707 [" = 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 & },}// parseUintBytes is like strconv.ParseUint, but using a []byte.func parseUintBytes( []byte, int, int) ( uint64, error) {var , uint64if == 0 { = int(strconv.IntSize) } := switch {caselen() < 1: = strconv.ErrSyntaxgotocase2 <= && <= 36:// valid base; nothing to docase == 0:// Look for octal, hex prefix.switch {case [0] == '0' && len() > 1 && ([1] == 'x' || [1] == 'X'): = 16 = [2:]iflen() < 1 { = strconv.ErrSyntaxgoto }case [0] == '0': = 8default: = 10 }default: = errors.New("invalid base " + strconv.Itoa())goto } = 0 = cutoff64() = 1<<uint() - 1for := 0; < len(); ++ {varbyte := []switch {case'0' <= && <= '9': = - '0'case'a' <= && <= 'z': = - 'a' + 10case'A' <= && <= 'Z': = - 'A' + 10default: = 0 = strconv.ErrSyntaxgoto }ifint() >= { = 0 = strconv.ErrSyntaxgoto }if >= {// n*base overflows = 1<<64 - 1 = strconv.ErrRangegoto } *= uint64() := + uint64()if < || > {// n+v overflows = 1<<64 - 1 = strconv.ErrRangegoto } = }return , nil:return , &strconv.NumError{Func: "ParseUint", Num: string(), Err: }}// Return the first number n such that n*base >= 1<<64.func cutoff64( int) uint64 {if < 2 {return0 }return (1<<64-1)/uint64() + 1}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.