| // Copyright 2015 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. | |
| package runtime_test | |
| import ( | |
| "runtime" | |
| "sync" | |
| "testing" | |
| ) | |
| type response struct { | |
| } | |
| type myError struct { | |
| } | |
| func (myError) Error() string { return "" } | |
| func doRequest(useSelect bool) (*response, error) { | |
| type async struct { | |
| resp *response | |
| err error | |
| } | |
| ch := make(chan *async, 0) | |
| done := make(chan struct{}, 0) | |
| if useSelect { | |
| go func() { | |
| select { | |
| case ch <- &async{resp: nil, err: myError{}}: | |
| case <-done: | |
| } | |
| }() | |
| } else { | |
| go func() { | |
| ch <- &async{resp: nil, err: myError{}} | |
| }() | |
| } | |
| r := <-ch | |
| runtime.Gosched() | |
| return r.resp, r.err | |
| } | |
| func TestChanSendSelectBarrier(t *testing.T) { | |
| testChanSendBarrier(true) | |
| } | |
| func TestChanSendBarrier(t *testing.T) { | |
| testChanSendBarrier(false) | |
| } | |
| func testChanSendBarrier(useSelect bool) { | |
| var wg sync.WaitGroup | |
| var globalMu sync.Mutex | |
| outer := 100 | |
| inner := 100000 | |
| if testing.Short() || runtime.GOARCH == "wasm" { | |
| outer = 10 | |
| inner = 1000 | |
| } | |
| for i := 0; i < outer; i++ { | |
| wg.Add(1) | |
| go func() { | |
| defer wg.Done() | |
| var garbage []byte | |
| for j := 0; j < inner; j++ { | |
| _, err := doRequest(useSelect) | |
| _, ok := err.(myError) | |
| if !ok { | |
| panic(1) | |
| } | |
| garbage = make([]byte, 1<<10) | |
| } | |
| globalMu.Lock() | |
| global = garbage | |
| globalMu.Unlock() | |
| }() | |
| } | |
| wg.Wait() | |
| } |