go doubleselect 源码

  • 2022-07-15
  • 浏览 (871)

golang doubleselect 代码

文件路径:/test/chan/doubleselect.go

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

// Test the situation in which 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 simpler 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)

	flag.Parse()
	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)
}

相关信息

go 源码目录

相关文章

go fifo 源码

go goroutines 源码

go nonblock 源码

go perm 源码

go powser1 源码

go powser2 源码

go select 源码

go select2 源码

go select3 源码

go select4 源码

0  赞