go/test/ken/chan.go

317 строки
4.2 KiB
Go
Исходник Обычный вид История

2008-09-20 07:52:59 +04:00
// $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 rand "rand"
type Chan
struct
{
sc,rc *chan int; // send and recv chan
sv,rv int; // send and recv seq
}
2008-09-20 07:52:59 +04:00
var
(
nproc int;
cval int;
End int = 10000;
totr,tots int;
nc *Chan;
2008-09-20 07:52:59 +04:00
)
func
init()
2008-09-20 07:52:59 +04:00
{
nc = new(Chan);
}
2008-09-20 07:52:59 +04:00
func
mkchan(c,n int) *[]*Chan
{
ca := new([]*Chan, n);
for i:=0; i<n; i++ {
cval = cval+100;
ch := new(Chan);
ch.sc = new(chan int, c);
ch.rc = ch.sc;
ch.sv = cval;
ch.rv = cval;
ca[i] = ch;
}
return ca;
2008-09-20 07:52:59 +04:00
}
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;
}
2008-09-20 07:52:59 +04:00
func
send(c *Chan)
2008-09-20 07:52:59 +04:00
{
nproc++; // total goroutines running
2008-09-20 07:52:59 +04:00
for {
for r:=rand.nrand(10); r>=0; r-- {
sys.gosched();
}
c.sc <- c.sv;
if c.send() {
2008-09-20 07:52:59 +04:00
break;
}
}
nproc--;
2008-09-20 07:52:59 +04:00
}
func (c *Chan)
recv(v int) bool
2008-09-20 07:52:59 +04:00
{
// print("recv ", v, "\n");
totr++;
c.rv = expect(c.rv, v);
if c.rv == End {
c.rc = nil;
return true;
2008-09-20 07:52:59 +04:00
}
return false;
2008-09-20 07:52:59 +04:00
}
func
recv(c *Chan)
2008-09-20 07:52:59 +04:00
{
var v int;
nproc++; // total goroutines running
for {
2008-09-20 07:52:59 +04:00
for r:=rand.nrand(10); r>=0; r-- {
sys.gosched();
}
v = <-c.rc;
if c.recv(v) {
2008-09-20 07:52:59 +04:00
break;
}
}
nproc--;
2008-09-20 07:52:59 +04:00
}
func
sel(r0,r1,r2,r3, s0,s1,s2,s3 *Chan)
2008-09-20 07:52:59 +04:00
{
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++ }
2008-09-20 07:52:59 +04:00
for {
for r:=rand.nrand(5); r>=0; r-- {
sys.gosched();
}
select {
case v = <-r0.rc:
if r0.recv(v) {
2008-09-20 07:52:59 +04:00
a--;
}
case v = <-r1.rc:
if r1.recv(v) {
2008-09-20 07:52:59 +04:00
a--;
}
case v = <-r2.rc:
if r2.recv(v) {
2008-09-20 07:52:59 +04:00
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() {
2008-09-20 07:52:59 +04:00
a--;
}
}
if a == 0 {
break;
}
}
nproc--;
2008-09-20 07:52:59 +04:00
}
// direct send to direct recv
func
test1(c *Chan)
2008-09-20 07:52:59 +04:00
{
go send(c);
go recv(c);
2008-09-20 07:52:59 +04:00
}
// direct send to select recv
func
test2(c int)
2008-09-20 07:52:59 +04:00
{
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);
2008-09-20 07:52:59 +04:00
}
// 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)
2008-09-20 07:52:59 +04:00
{
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]);
2008-09-20 07:52:59 +04:00
}
// wait for outstanding tests to finish
func
wait()
{
sys.gosched();
for nproc != 0 {
2008-09-20 07:52:59 +04:00
sys.gosched();
}
}
// run all tests with specified buffer size
func
tests(c int)
2008-09-20 07:52:59 +04:00
{
ca := mkchan(c,4);
test1(ca[0]);
test1(ca[1]);
test1(ca[2]);
test1(ca[3]);
wait();
test2(c);
wait();
test3(c);
2008-09-20 07:52:59 +04:00
wait();
test4(c);
2008-09-20 07:52:59 +04:00
wait();
test5(c);
wait();
test6(c);
2008-09-20 07:52:59 +04:00
wait();
}
// run all test with 4 buffser sizes
func
main()
{
2008-09-20 07:52:59 +04:00
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");
sys.exit(1);
}
2008-09-20 07:52:59 +04:00
sys.exit(0);
}