| // $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. |
| |
| // Test close(c), closed(c). |
| // |
| // TODO(rsc): Doesn't check behavior of close(c) when there |
| // are blocked senders/receivers. |
| |
| package main |
| |
| type Chan interface { |
| Send(int); |
| Nbsend(int) bool; |
| Recv() int; |
| Nbrecv() (int, bool); |
| Close(); |
| Closed() bool; |
| Impl() string; |
| } |
| |
| // direct channel operations |
| type XChan chan int |
| func (c XChan) Send(x int) { |
| c <- x |
| } |
| |
| func (c XChan) Nbsend(x int) bool { |
| return c <- x; |
| } |
| |
| func (c XChan) Recv() int { |
| return <-c |
| } |
| |
| func (c XChan) Nbrecv() (int, bool) { |
| x, ok := <-c; |
| return x, ok; |
| } |
| |
| func (c XChan) Close() { |
| close(c) |
| } |
| |
| func (c XChan) Closed() bool { |
| return closed(c) |
| } |
| |
| func (c XChan) Impl() string { |
| return "(<- operator)" |
| } |
| |
| // indirect operations via select |
| type SChan chan int |
| func (c SChan) Send(x int) { |
| select { |
| case c <- x: |
| } |
| } |
| |
| func (c SChan) Nbsend(x int) bool { |
| select { |
| case c <- x: |
| return true; |
| default: |
| return false; |
| } |
| panic("nbsend"); |
| } |
| |
| func (c SChan) Recv() int { |
| select { |
| case x := <-c: |
| return x; |
| } |
| panic("recv"); |
| } |
| |
| func (c SChan) Nbrecv() (int, bool) { |
| select { |
| case x := <-c: |
| return x, true; |
| default: |
| return 0, false; |
| } |
| panic("nbrecv"); |
| } |
| |
| func (c SChan) Close() { |
| close(c) |
| } |
| |
| func (c SChan) Closed() bool { |
| return closed(c) |
| } |
| |
| func (c SChan) Impl() string { |
| return "(select)"; |
| } |
| |
| func test1(c Chan) { |
| // not closed until the close signal (a zero value) has been received. |
| if c.Closed() { |
| println("test1: Closed before Recv zero:", c.Impl()); |
| } |
| |
| for i := 0; i < 3; i++ { |
| // recv a close signal (a zero value) |
| if x := c.Recv(); x != 0 { |
| println("test1: recv on closed got non-zero:", x, c.Impl()); |
| } |
| |
| // should now be closed. |
| if !c.Closed() { |
| println("test1: not closed after recv zero", c.Impl()); |
| } |
| |
| // should work with ,ok: received a value without blocking, so ok == true. |
| x, ok := c.Nbrecv(); |
| if !ok { |
| println("test1: recv on closed got not ok", c.Impl()); |
| } |
| if x != 0 { |
| println("test1: recv ,ok on closed got non-zero:", x, c.Impl()); |
| } |
| } |
| |
| // send should work with ,ok too: sent a value without blocking, so ok == true. |
| ok := c.Nbsend(1); |
| if !ok { |
| println("test1: send on closed got not ok", c.Impl()); |
| } |
| |
| // but the value should have been discarded. |
| if x := c.Recv(); x != 0 { |
| println("test1: recv on closed got non-zero after send on closed:", x, c.Impl()); |
| } |
| |
| // similarly Send. |
| c.Send(2); |
| if x := c.Recv(); x != 0 { |
| println("test1: recv on closed got non-zero after send on closed:", x, c.Impl()); |
| } |
| } |
| |
| func testasync1(c Chan) { |
| // not closed until the close signal (a zero value) has been received. |
| if c.Closed() { |
| println("testasync1: Closed before Recv zero:", c.Impl()); |
| } |
| |
| // should be able to get the last value via Recv |
| if x := c.Recv(); x != 1 { |
| println("testasync1: Recv did not get 1:", x, c.Impl()); |
| } |
| |
| test1(c); |
| } |
| |
| func testasync2(c Chan) { |
| // not closed until the close signal (a zero value) has been received. |
| if c.Closed() { |
| println("testasync2: Closed before Recv zero:", c.Impl()); |
| } |
| |
| // should be able to get the last value via Nbrecv |
| if x, ok := c.Nbrecv(); !ok || x != 1 { |
| println("testasync2: Nbrecv did not get 1, true:", x, ok, c.Impl()); |
| } |
| |
| test1(c); |
| } |
| |
| func closedsync() chan int { |
| c := make(chan int); |
| close(c); |
| return c; |
| } |
| |
| func closedasync() chan int { |
| c := make(chan int, 2); |
| c <- 1; |
| close(c); |
| return c; |
| } |
| |
| func main() { |
| test1(XChan(closedsync())); |
| test1(SChan(closedsync())); |
| |
| testasync1(XChan(closedasync())); |
| testasync1(SChan(closedasync())); |
| testasync2(XChan(closedasync())); |
| testasync2(SChan(closedasync())); |
| } |