modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/test/ken/chan.go (about)

     1  // run
     2  
     3  // Copyright 2009 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Test communication operations including select.
     8  
     9  package main
    10  
    11  import "os"
    12  import "runtime"
    13  import "sync"
    14  
    15  var randx int
    16  
    17  func nrand(n int) int {
    18  	randx += 10007
    19  	if randx >= 1000000 {
    20  		randx -= 1000000
    21  	}
    22  	return randx % n
    23  }
    24  
    25  type Chan struct {
    26  	sc, rc chan int // send and recv chan
    27  	sv, rv int      // send and recv seq
    28  }
    29  
    30  var (
    31  	nproc      int
    32  	nprocLock  sync.Mutex
    33  	cval       int
    34  	end        int = 10000
    35  	totr, tots int
    36  	totLock    sync.Mutex
    37  	nc         *Chan
    38  )
    39  
    40  func init() {
    41  	nc = new(Chan)
    42  }
    43  
    44  func changeNproc(adjust int) int {
    45  	nprocLock.Lock()
    46  	nproc += adjust
    47  	ret := nproc
    48  	nprocLock.Unlock()
    49  	return ret
    50  }
    51  
    52  func mkchan(c, n int) []*Chan {
    53  	ca := make([]*Chan, n)
    54  	for i := 0; i < n; i++ {
    55  		cval = cval + 100
    56  		ch := new(Chan)
    57  		ch.sc = make(chan int, c)
    58  		ch.rc = ch.sc
    59  		ch.sv = cval
    60  		ch.rv = cval
    61  		ca[i] = ch
    62  	}
    63  	return ca
    64  }
    65  
    66  func expect(v, v0 int) (newv int) {
    67  	if v == v0 {
    68  		if v%100 == 75 {
    69  			return end
    70  		}
    71  		return v + 1
    72  	}
    73  	print("got ", v, " expected ", v0+1, "\n")
    74  	panic("fail")
    75  }
    76  
    77  func (c *Chan) send() bool {
    78  	//	print("send ", c.sv, "\n");
    79  	totLock.Lock()
    80  	tots++
    81  	totLock.Unlock()
    82  	c.sv = expect(c.sv, c.sv)
    83  	if c.sv == end {
    84  		c.sc = nil
    85  		return true
    86  	}
    87  	return false
    88  }
    89  
    90  func send(c *Chan) {
    91  	for {
    92  		for r := nrand(10); r >= 0; r-- {
    93  			runtime.Gosched()
    94  		}
    95  		c.sc <- c.sv
    96  		if c.send() {
    97  			break
    98  		}
    99  	}
   100  	changeNproc(-1)
   101  }
   102  
   103  func (c *Chan) recv(v int) bool {
   104  	//	print("recv ", v, "\n");
   105  	totLock.Lock()
   106  	totr++
   107  	totLock.Unlock()
   108  	c.rv = expect(c.rv, v)
   109  	if c.rv == end {
   110  		c.rc = nil
   111  		return true
   112  	}
   113  	return false
   114  }
   115  
   116  func recv(c *Chan) {
   117  	var v int
   118  
   119  	for {
   120  		for r := nrand(10); r >= 0; r-- {
   121  			runtime.Gosched()
   122  		}
   123  		v = <-c.rc
   124  		if c.recv(v) {
   125  			break
   126  		}
   127  	}
   128  	changeNproc(-1)
   129  }
   130  
   131  func sel(r0, r1, r2, r3, s0, s1, s2, s3 *Chan) {
   132  	var v int
   133  
   134  	a := 0 // local chans running
   135  
   136  	if r0.rc != nil {
   137  		a++
   138  	}
   139  	if r1.rc != nil {
   140  		a++
   141  	}
   142  	if r2.rc != nil {
   143  		a++
   144  	}
   145  	if r3.rc != nil {
   146  		a++
   147  	}
   148  	if s0.sc != nil {
   149  		a++
   150  	}
   151  	if s1.sc != nil {
   152  		a++
   153  	}
   154  	if s2.sc != nil {
   155  		a++
   156  	}
   157  	if s3.sc != nil {
   158  		a++
   159  	}
   160  
   161  	for {
   162  		for r := nrand(5); r >= 0; r-- {
   163  			runtime.Gosched()
   164  		}
   165  
   166  		select {
   167  		case v = <-r0.rc:
   168  			if r0.recv(v) {
   169  				a--
   170  			}
   171  		case v = <-r1.rc:
   172  			if r1.recv(v) {
   173  				a--
   174  			}
   175  		case v = <-r2.rc:
   176  			if r2.recv(v) {
   177  				a--
   178  			}
   179  		case v = <-r3.rc:
   180  			if r3.recv(v) {
   181  				a--
   182  			}
   183  		case s0.sc <- s0.sv:
   184  			if s0.send() {
   185  				a--
   186  			}
   187  		case s1.sc <- s1.sv:
   188  			if s1.send() {
   189  				a--
   190  			}
   191  		case s2.sc <- s2.sv:
   192  			if s2.send() {
   193  				a--
   194  			}
   195  		case s3.sc <- s3.sv:
   196  			if s3.send() {
   197  				a--
   198  			}
   199  		}
   200  		if a == 0 {
   201  			break
   202  		}
   203  	}
   204  	changeNproc(-1)
   205  }
   206  
   207  // direct send to direct recv
   208  func test1(c *Chan) {
   209  	changeNproc(2)
   210  	go send(c)
   211  	go recv(c)
   212  }
   213  
   214  // direct send to select recv
   215  func test2(c int) {
   216  	ca := mkchan(c, 4)
   217  
   218  	changeNproc(4)
   219  	go send(ca[0])
   220  	go send(ca[1])
   221  	go send(ca[2])
   222  	go send(ca[3])
   223  
   224  	changeNproc(1)
   225  	go sel(ca[0], ca[1], ca[2], ca[3], nc, nc, nc, nc)
   226  }
   227  
   228  // select send to direct recv
   229  func test3(c int) {
   230  	ca := mkchan(c, 4)
   231  
   232  	changeNproc(4)
   233  	go recv(ca[0])
   234  	go recv(ca[1])
   235  	go recv(ca[2])
   236  	go recv(ca[3])
   237  
   238  	changeNproc(1)
   239  	go sel(nc, nc, nc, nc, ca[0], ca[1], ca[2], ca[3])
   240  }
   241  
   242  // select send to select recv
   243  func test4(c int) {
   244  	ca := mkchan(c, 4)
   245  
   246  	changeNproc(2)
   247  	go sel(nc, nc, nc, nc, ca[0], ca[1], ca[2], ca[3])
   248  	go sel(ca[0], ca[1], ca[2], ca[3], nc, nc, nc, nc)
   249  }
   250  
   251  func test5(c int) {
   252  	ca := mkchan(c, 8)
   253  
   254  	changeNproc(2)
   255  	go sel(ca[4], ca[5], ca[6], ca[7], ca[0], ca[1], ca[2], ca[3])
   256  	go sel(ca[0], ca[1], ca[2], ca[3], ca[4], ca[5], ca[6], ca[7])
   257  }
   258  
   259  func test6(c int) {
   260  	ca := mkchan(c, 12)
   261  
   262  	changeNproc(4)
   263  	go send(ca[4])
   264  	go send(ca[5])
   265  	go send(ca[6])
   266  	go send(ca[7])
   267  
   268  	changeNproc(4)
   269  	go recv(ca[8])
   270  	go recv(ca[9])
   271  	go recv(ca[10])
   272  	go recv(ca[11])
   273  
   274  	changeNproc(2)
   275  	go sel(ca[4], ca[5], ca[6], ca[7], ca[0], ca[1], ca[2], ca[3])
   276  	go sel(ca[0], ca[1], ca[2], ca[3], ca[8], ca[9], ca[10], ca[11])
   277  }
   278  
   279  // wait for outstanding tests to finish
   280  func wait() {
   281  	runtime.Gosched()
   282  	for changeNproc(0) != 0 {
   283  		runtime.Gosched()
   284  	}
   285  }
   286  
   287  // run all tests with specified buffer size
   288  func tests(c int) {
   289  	ca := mkchan(c, 4)
   290  	test1(ca[0])
   291  	test1(ca[1])
   292  	test1(ca[2])
   293  	test1(ca[3])
   294  	wait()
   295  
   296  	test2(c)
   297  	wait()
   298  
   299  	test3(c)
   300  	wait()
   301  
   302  	test4(c)
   303  	wait()
   304  
   305  	test5(c)
   306  	wait()
   307  
   308  	test6(c)
   309  	wait()
   310  }
   311  
   312  // run all test with 4 buffser sizes
   313  func main() {
   314  
   315  	tests(0)
   316  	tests(1)
   317  	tests(10)
   318  	tests(100)
   319  
   320  	t := 4 * // buffer sizes
   321  		(4*4 + // tests 1,2,3,4 channels
   322  			8 + // test 5 channels
   323  			12) * // test 6 channels
   324  		76 // sends/recvs on a channel
   325  
   326  	if tots != t || totr != t {
   327  		print("tots=", tots, " totr=", totr, " sb=", t, "\n")
   328  		os.Exit(1)
   329  	}
   330  	os.Exit(0)
   331  }