blob: c7c759be3b3edfcad980be8dd0155493db7f7aab [file] [log] [blame]
Russ Cox13584f42009-03-23 18:50:35 -07001// $G $D/$F.go && $L $F.$A && ./$A.out
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 close(c), closed(c).
8//
9// TODO(rsc): Doesn't check behavior of close(c) when there
10// are blocked senders/receivers.
11
12package main
13
14type Chan interface {
Rob Pike4f61fc92010-09-04 10:36:13 +100015 Send(int)
16 Nbsend(int) bool
17 Recv() int
18 Nbrecv() (int, bool)
19 Close()
20 Closed() bool
21 Impl() string
Russ Cox13584f42009-03-23 18:50:35 -070022}
23
24// direct channel operations
25type XChan chan int
26func (c XChan) Send(x int) {
27 c <- x
28}
29
30func (c XChan) Nbsend(x int) bool {
Rob Pike4f61fc92010-09-04 10:36:13 +100031 return c <- x
Russ Cox13584f42009-03-23 18:50:35 -070032}
33
34func (c XChan) Recv() int {
35 return <-c
36}
37
38func (c XChan) Nbrecv() (int, bool) {
Rob Pike4f61fc92010-09-04 10:36:13 +100039 x, ok := <-c
40 return x, ok
Russ Cox13584f42009-03-23 18:50:35 -070041}
42
43func (c XChan) Close() {
44 close(c)
45}
46
47func (c XChan) Closed() bool {
48 return closed(c)
49}
50
51func (c XChan) Impl() string {
52 return "(<- operator)"
53}
54
55// indirect operations via select
56type SChan chan int
57func (c SChan) Send(x int) {
58 select {
59 case c <- x:
60 }
61}
62
63func (c SChan) Nbsend(x int) bool {
64 select {
65 case c <- x:
Rob Pike4f61fc92010-09-04 10:36:13 +100066 return true
Russ Cox13584f42009-03-23 18:50:35 -070067 default:
Rob Pike4f61fc92010-09-04 10:36:13 +100068 return false
Russ Cox13584f42009-03-23 18:50:35 -070069 }
Rob Pike4f61fc92010-09-04 10:36:13 +100070 panic("nbsend")
Russ Cox13584f42009-03-23 18:50:35 -070071}
72
73func (c SChan) Recv() int {
74 select {
75 case x := <-c:
Rob Pike4f61fc92010-09-04 10:36:13 +100076 return x
Russ Cox13584f42009-03-23 18:50:35 -070077 }
Rob Pike4f61fc92010-09-04 10:36:13 +100078 panic("recv")
Russ Cox13584f42009-03-23 18:50:35 -070079}
80
81func (c SChan) Nbrecv() (int, bool) {
82 select {
83 case x := <-c:
Rob Pike4f61fc92010-09-04 10:36:13 +100084 return x, true
Russ Cox13584f42009-03-23 18:50:35 -070085 default:
Rob Pike4f61fc92010-09-04 10:36:13 +100086 return 0, false
Russ Cox13584f42009-03-23 18:50:35 -070087 }
Rob Pike4f61fc92010-09-04 10:36:13 +100088 panic("nbrecv")
Russ Cox13584f42009-03-23 18:50:35 -070089}
90
91func (c SChan) Close() {
92 close(c)
93}
94
95func (c SChan) Closed() bool {
96 return closed(c)
97}
98
99func (c SChan) Impl() string {
Rob Pike4f61fc92010-09-04 10:36:13 +1000100 return "(select)"
Russ Cox13584f42009-03-23 18:50:35 -0700101}
102
103func test1(c Chan) {
104 // not closed until the close signal (a zero value) has been received.
105 if c.Closed() {
Rob Pike4f61fc92010-09-04 10:36:13 +1000106 println("test1: Closed before Recv zero:", c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700107 }
108
109 for i := 0; i < 3; i++ {
110 // recv a close signal (a zero value)
111 if x := c.Recv(); x != 0 {
Rob Pike4f61fc92010-09-04 10:36:13 +1000112 println("test1: recv on closed got non-zero:", x, c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700113 }
114
115 // should now be closed.
116 if !c.Closed() {
Rob Pike4f61fc92010-09-04 10:36:13 +1000117 println("test1: not closed after recv zero", c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700118 }
119
120 // should work with ,ok: received a value without blocking, so ok == true.
Rob Pike4f61fc92010-09-04 10:36:13 +1000121 x, ok := c.Nbrecv()
Russ Cox13584f42009-03-23 18:50:35 -0700122 if !ok {
Rob Pike4f61fc92010-09-04 10:36:13 +1000123 println("test1: recv on closed got not ok", c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700124 }
125 if x != 0 {
Rob Pike4f61fc92010-09-04 10:36:13 +1000126 println("test1: recv ,ok on closed got non-zero:", x, c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700127 }
128 }
129
130 // send should work with ,ok too: sent a value without blocking, so ok == true.
Rob Pike4f61fc92010-09-04 10:36:13 +1000131 ok := c.Nbsend(1)
Russ Cox13584f42009-03-23 18:50:35 -0700132 if !ok {
Rob Pike4f61fc92010-09-04 10:36:13 +1000133 println("test1: send on closed got not ok", c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700134 }
135
136 // but the value should have been discarded.
137 if x := c.Recv(); x != 0 {
Rob Pike4f61fc92010-09-04 10:36:13 +1000138 println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700139 }
140
141 // similarly Send.
Rob Pike4f61fc92010-09-04 10:36:13 +1000142 c.Send(2)
Russ Cox13584f42009-03-23 18:50:35 -0700143 if x := c.Recv(); x != 0 {
Rob Pike4f61fc92010-09-04 10:36:13 +1000144 println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700145 }
146}
147
148func testasync1(c Chan) {
149 // not closed until the close signal (a zero value) has been received.
150 if c.Closed() {
Rob Pike4f61fc92010-09-04 10:36:13 +1000151 println("testasync1: Closed before Recv zero:", c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700152 }
153
154 // should be able to get the last value via Recv
155 if x := c.Recv(); x != 1 {
Rob Pike4f61fc92010-09-04 10:36:13 +1000156 println("testasync1: Recv did not get 1:", x, c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700157 }
158
Rob Pike4f61fc92010-09-04 10:36:13 +1000159 test1(c)
Russ Cox13584f42009-03-23 18:50:35 -0700160}
161
162func testasync2(c Chan) {
163 // not closed until the close signal (a zero value) has been received.
164 if c.Closed() {
Rob Pike4f61fc92010-09-04 10:36:13 +1000165 println("testasync2: Closed before Recv zero:", c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700166 }
167
168 // should be able to get the last value via Nbrecv
169 if x, ok := c.Nbrecv(); !ok || x != 1 {
Rob Pike4f61fc92010-09-04 10:36:13 +1000170 println("testasync2: Nbrecv did not get 1, true:", x, ok, c.Impl())
Russ Cox13584f42009-03-23 18:50:35 -0700171 }
172
Rob Pike4f61fc92010-09-04 10:36:13 +1000173 test1(c)
Russ Cox13584f42009-03-23 18:50:35 -0700174}
175
176func closedsync() chan int {
Rob Pike4f61fc92010-09-04 10:36:13 +1000177 c := make(chan int)
178 close(c)
179 return c
Russ Cox13584f42009-03-23 18:50:35 -0700180}
181
182func closedasync() chan int {
Rob Pike4f61fc92010-09-04 10:36:13 +1000183 c := make(chan int, 2)
184 c <- 1
185 close(c)
186 return c
Russ Cox13584f42009-03-23 18:50:35 -0700187}
188
189func main() {
Rob Pike4f61fc92010-09-04 10:36:13 +1000190 test1(XChan(closedsync()))
191 test1(SChan(closedsync()))
Russ Cox13584f42009-03-23 18:50:35 -0700192
Rob Pike4f61fc92010-09-04 10:36:13 +1000193 testasync1(XChan(closedasync()))
194 testasync1(SChan(closedasync()))
195 testasync2(XChan(closedasync()))
196 testasync2(SChan(closedasync()))
Russ Cox13584f42009-03-23 18:50:35 -0700197}