github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/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 }