OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [testsuite/] [go.test/] [test/] [chan/] [doubleselect.go] - Rev 700

Compare with Previous | Blame | View Log

// $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.

// This test is designed to flush out the case where two cases of a select can
// both end up running. See http://codereview.appspot.com/180068.
package main

import (
        "flag"
        "runtime"
)

var iterations *int = flag.Int("n", 100000, "number of iterations")

// sender sends a counter to one of four different channels. If two
// cases both end up running in the same iteration, the same value will be sent
// to two different channels.
func sender(n int, c1, c2, c3, c4 chan<- int) {
        defer close(c1)
        defer close(c2)
        defer close(c3)
        defer close(c4)

        for i := 0; i < n; i++ {
                select {
                case c1 <- i:
                case c2 <- i:
                case c3 <- i:
                case c4 <- i:
                }
        }
}

// mux receives the values from sender and forwards them onto another channel.
// It would be simplier to just have sender's four cases all be the same
// channel, but this doesn't actually trigger the bug.
func mux(out chan<- int, in <-chan int, done chan<- bool) {
        for v := range in {
                out <- v
        }
        done <- true
}

// recver gets a steam of values from the four mux's and checks for duplicates.
func recver(in <-chan int) {
        seen := make(map[int]bool)

        for v := range in {
                if _, ok := seen[v]; ok {
                        println("got duplicate value: ", v)
                        panic("fail")
                }
                seen[v] = true
        }
}

func main() {
        runtime.GOMAXPROCS(2)

        c1 := make(chan int)
        c2 := make(chan int)
        c3 := make(chan int)
        c4 := make(chan int)
        done := make(chan bool)
        cmux := make(chan int)
        go sender(*iterations, c1, c2, c3, c4)
        go mux(cmux, c1, done)
        go mux(cmux, c2, done)
        go mux(cmux, c3, done)
        go mux(cmux, c4, done)
        go func() {
                <-done
                <-done
                <-done
                <-done
                close(cmux)
        }()
        // We keep the recver because it might catch more bugs in the future.
        // However, the result of the bug linked to at the top is that we'll
        // end up panicking with: "throw: bad g->status in ready".
        recver(cmux)
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.