// run

// 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"
import "sync"

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
	nprocLock  sync.Mutex
	cval       int
	end        int = 10000
	totr, tots int
	totLock    sync.Mutex
	nc         *Chan
)

func init() {
	nc = new(Chan)
}

func changeNproc(adjust int) int {
	nprocLock.Lock()
	nproc += adjust
	ret := nproc
	nprocLock.Unlock()
	return ret
}

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
	}
	print("got ", v, " expected ", v0+1, "\n")
	panic("fail")
}

func (c *Chan) send() bool {
	//	print("send ", c.sv, "\n");
	totLock.Lock()
	tots++
	totLock.Unlock()
	c.sv = expect(c.sv, c.sv)
	if c.sv == end {
		c.sc = nil
		return true
	}
	return false
}

func send(c *Chan) {
	for {
		for r := nrand(10); r >= 0; r-- {
			runtime.Gosched()
		}
		c.sc <- c.sv
		if c.send() {
			break
		}
	}
	changeNproc(-1)
}

func (c *Chan) recv(v int) bool {
	//	print("recv ", v, "\n");
	totLock.Lock()
	totr++
	totLock.Unlock()
	c.rv = expect(c.rv, v)
	if c.rv == end {
		c.rc = nil
		return true
	}
	return false
}

func recv(c *Chan) {
	var v int

	for {
		for r := nrand(10); r >= 0; r-- {
			runtime.Gosched()
		}
		v = <-c.rc
		if c.recv(v) {
			break
		}
	}
	changeNproc(-1)
}

func sel(r0, r1, r2, r3, s0, s1, s2, s3 *Chan) {
	var v int

	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
		}
	}
	changeNproc(-1)
}

// direct send to direct recv
func test1(c *Chan) {
	changeNproc(2)
	go send(c)
	go recv(c)
}

// direct send to select recv
func test2(c int) {
	ca := mkchan(c, 4)

	changeNproc(4)
	go send(ca[0])
	go send(ca[1])
	go send(ca[2])
	go send(ca[3])

	changeNproc(1)
	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)

	changeNproc(4)
	go recv(ca[0])
	go recv(ca[1])
	go recv(ca[2])
	go recv(ca[3])

	changeNproc(1)
	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)

	changeNproc(2)
	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)

	changeNproc(2)
	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)

	changeNproc(4)
	go send(ca[4])
	go send(ca[5])
	go send(ca[6])
	go send(ca[7])

	changeNproc(4)
	go recv(ca[8])
	go recv(ca[9])
	go recv(ca[10])
	go recv(ca[11])

	changeNproc(2)
	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 changeNproc(0) != 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)
}
