mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00:00
330 lines
4.3 KiB
Go
330 lines
4.3 KiB
Go
// $G $D/$F.go && $L $F.$A && ./$A.out
|
|
|
|
// Copyright 2009 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 main
|
|
|
|
import "os"
|
|
import "runtime"
|
|
|
|
var randx int;
|
|
|
|
func
|
|
nrand(n int) int
|
|
{
|
|
randx += 10007;
|
|
if randx >= 1000000 {
|
|
randx -= 1000000;
|
|
}
|
|
return randx%n;
|
|
}
|
|
|
|
type Chan
|
|
struct
|
|
{
|
|
sc,rc chan int; // send and recv chan
|
|
sv,rv int; // send and recv seq
|
|
}
|
|
|
|
var
|
|
(
|
|
nproc int;
|
|
cval int;
|
|
end int = 10000;
|
|
totr,tots int;
|
|
nc *Chan;
|
|
)
|
|
|
|
func
|
|
init()
|
|
{
|
|
nc = new(Chan);
|
|
}
|
|
|
|
func
|
|
mkchan(c,n int) []*Chan
|
|
{
|
|
ca := make([]*Chan, n);
|
|
for i:=0; i<n; i++ {
|
|
cval = cval+100;
|
|
ch := new(Chan);
|
|
ch.sc = make(chan int, c);
|
|
ch.rc = ch.sc;
|
|
ch.sv = cval;
|
|
ch.rv = cval;
|
|
ca[i] = ch;
|
|
}
|
|
return ca;
|
|
}
|
|
|
|
func
|
|
expect(v, v0 int) (newv int)
|
|
{
|
|
if v == v0 {
|
|
if v%100 == 75 {
|
|
return end;
|
|
}
|
|
return v+1;
|
|
}
|
|
panic("got ", v, " expected ", v0+1, "\n");
|
|
}
|
|
|
|
func (c *Chan)
|
|
send() bool
|
|
{
|
|
// print("send ", c.sv, "\n");
|
|
tots++;
|
|
c.sv = expect(c.sv, c.sv);
|
|
if c.sv == end {
|
|
c.sc = nil;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
func
|
|
send(c *Chan)
|
|
{
|
|
nproc++; // total goroutines running
|
|
for {
|
|
for r:=nrand(10); r>=0; r-- {
|
|
runtime.Gosched();
|
|
}
|
|
c.sc <- c.sv;
|
|
if c.send() {
|
|
break;
|
|
}
|
|
}
|
|
nproc--;
|
|
}
|
|
|
|
func (c *Chan)
|
|
recv(v int) bool
|
|
{
|
|
// print("recv ", v, "\n");
|
|
totr++;
|
|
c.rv = expect(c.rv, v);
|
|
if c.rv == end {
|
|
c.rc = nil;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
func
|
|
recv(c *Chan)
|
|
{
|
|
var v int;
|
|
|
|
nproc++; // total goroutines running
|
|
for {
|
|
for r:=nrand(10); r>=0; r-- {
|
|
runtime.Gosched();
|
|
}
|
|
v = <-c.rc;
|
|
if c.recv(v) {
|
|
break;
|
|
}
|
|
}
|
|
nproc--;
|
|
}
|
|
|
|
func
|
|
sel(r0,r1,r2,r3, s0,s1,s2,s3 *Chan)
|
|
{
|
|
var v int;
|
|
|
|
nproc++; // total goroutines running
|
|
a := 0; // local chans running
|
|
|
|
if r0.rc != nil { a++ }
|
|
if r1.rc != nil { a++ }
|
|
if r2.rc != nil { a++ }
|
|
if r3.rc != nil { a++ }
|
|
if s0.sc != nil { a++ }
|
|
if s1.sc != nil { a++ }
|
|
if s2.sc != nil { a++ }
|
|
if s3.sc != nil { a++ }
|
|
|
|
for {
|
|
for r:=nrand(5); r>=0; r-- {
|
|
runtime.Gosched();
|
|
}
|
|
|
|
select {
|
|
case v = <-r0.rc:
|
|
if r0.recv(v) {
|
|
a--;
|
|
}
|
|
case v = <-r1.rc:
|
|
if r1.recv(v) {
|
|
a--;
|
|
}
|
|
case v = <-r2.rc:
|
|
if r2.recv(v) {
|
|
a--;
|
|
}
|
|
case v = <-r3.rc:
|
|
if r3.recv(v) {
|
|
a--;
|
|
}
|
|
case s0.sc <- s0.sv:
|
|
if s0.send() {
|
|
a--;
|
|
}
|
|
case s1.sc <- s1.sv:
|
|
if s1.send() {
|
|
a--;
|
|
}
|
|
case s2.sc <- s2.sv:
|
|
if s2.send() {
|
|
a--;
|
|
}
|
|
case s3.sc <- s3.sv:
|
|
if s3.send() {
|
|
a--;
|
|
}
|
|
}
|
|
if a == 0 {
|
|
break;
|
|
}
|
|
}
|
|
nproc--;
|
|
}
|
|
|
|
// direct send to direct recv
|
|
func
|
|
test1(c *Chan)
|
|
{
|
|
go send(c);
|
|
go recv(c);
|
|
}
|
|
|
|
// direct send to select recv
|
|
func
|
|
test2(c int)
|
|
{
|
|
ca := mkchan(c,4);
|
|
|
|
go send(ca[0]);
|
|
go send(ca[1]);
|
|
go send(ca[2]);
|
|
go send(ca[3]);
|
|
|
|
go sel(ca[0],ca[1],ca[2],ca[3], nc,nc,nc,nc);
|
|
}
|
|
|
|
// select send to direct recv
|
|
func
|
|
test3(c int)
|
|
{
|
|
ca := mkchan(c,4);
|
|
|
|
go recv(ca[0]);
|
|
go recv(ca[1]);
|
|
go recv(ca[2]);
|
|
go recv(ca[3]);
|
|
|
|
go sel(nc,nc,nc,nc, ca[0],ca[1],ca[2],ca[3]);
|
|
}
|
|
|
|
// select send to select recv
|
|
func
|
|
test4(c int)
|
|
{
|
|
ca := mkchan(c,4);
|
|
|
|
go sel(nc,nc,nc,nc, ca[0],ca[1],ca[2],ca[3]);
|
|
go sel(ca[0],ca[1],ca[2],ca[3], nc,nc,nc,nc);
|
|
}
|
|
|
|
func
|
|
test5(c int)
|
|
{
|
|
ca := mkchan(c,8);
|
|
|
|
go sel(ca[4],ca[5],ca[6],ca[7], ca[0],ca[1],ca[2],ca[3]);
|
|
go sel(ca[0],ca[1],ca[2],ca[3], ca[4],ca[5],ca[6],ca[7]);
|
|
}
|
|
|
|
func
|
|
test6(c int)
|
|
{
|
|
ca := mkchan(c,12);
|
|
|
|
go send(ca[4]);
|
|
go send(ca[5]);
|
|
go send(ca[6]);
|
|
go send(ca[7]);
|
|
|
|
go recv(ca[8]);
|
|
go recv(ca[9]);
|
|
go recv(ca[10]);
|
|
go recv(ca[11]);
|
|
|
|
go sel(ca[4],ca[5],ca[6],ca[7], ca[0],ca[1],ca[2],ca[3]);
|
|
go sel(ca[0],ca[1],ca[2],ca[3], ca[8],ca[9],ca[10],ca[11]);
|
|
}
|
|
|
|
// wait for outstanding tests to finish
|
|
func
|
|
wait()
|
|
{
|
|
runtime.Gosched();
|
|
for nproc != 0 {
|
|
runtime.Gosched();
|
|
}
|
|
}
|
|
|
|
// run all tests with specified buffer size
|
|
func
|
|
tests(c int)
|
|
{
|
|
ca := mkchan(c,4);
|
|
test1(ca[0]);
|
|
test1(ca[1]);
|
|
test1(ca[2]);
|
|
test1(ca[3]);
|
|
wait();
|
|
|
|
test2(c);
|
|
wait();
|
|
|
|
test3(c);
|
|
wait();
|
|
|
|
test4(c);
|
|
wait();
|
|
|
|
test5(c);
|
|
wait();
|
|
|
|
test6(c);
|
|
wait();
|
|
}
|
|
|
|
// run all test with 4 buffser sizes
|
|
func
|
|
main()
|
|
{
|
|
|
|
tests(0);
|
|
tests(1);
|
|
tests(10);
|
|
tests(100);
|
|
|
|
t := 4 // buffer sizes
|
|
* ( 4*4 // tests 1,2,3,4 channels
|
|
+ 8 // test 5 channels
|
|
+ 12 // test 6 channels
|
|
) * 76; // sends/recvs on a channel
|
|
|
|
if tots != t || totr != t {
|
|
print("tots=", tots, " totr=", totr, " sb=", t, "\n");
|
|
os.Exit(1);
|
|
}
|
|
os.Exit(0);
|
|
}
|