mirror of
https://github.com/golang/go
synced 2024-11-22 01:04:40 -07:00
go code: replace closed(c) with x, ok := <-c
R=golang-dev, rog, bradfitzwork, r CC=golang-dev https://golang.org/cl/4243072
This commit is contained in:
parent
8bf34e3356
commit
3f915f51a8
@ -306,7 +306,7 @@ func (nch *netChan) sender() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Receive value from local side for sending to remote side.
|
// Receive value from local side for sending to remote side.
|
||||||
func (nch *netChan) recv() (val reflect.Value, closed bool) {
|
func (nch *netChan) recv() (val reflect.Value, ok bool) {
|
||||||
if nch.dir != Send {
|
if nch.dir != Send {
|
||||||
panic("recv on wrong direction of channel")
|
panic("recv on wrong direction of channel")
|
||||||
}
|
}
|
||||||
@ -317,7 +317,7 @@ func (nch *netChan) recv() (val reflect.Value, closed bool) {
|
|||||||
nch.space++
|
nch.space++
|
||||||
}
|
}
|
||||||
nch.space--
|
nch.space--
|
||||||
return nch.ch.Recv(), nch.ch.Closed()
|
return nch.ch.Recv()
|
||||||
}
|
}
|
||||||
|
|
||||||
// acked is called when the remote side indicates that
|
// acked is called when the remote side indicates that
|
||||||
|
@ -181,8 +181,8 @@ func (client *expClient) run() {
|
|||||||
// The header is passed by value to avoid issues of overwriting.
|
// The header is passed by value to avoid issues of overwriting.
|
||||||
func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) {
|
func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) {
|
||||||
for {
|
for {
|
||||||
val, closed := nch.recv()
|
val, ok := nch.recv()
|
||||||
if closed {
|
if !ok {
|
||||||
if err := client.encode(&hdr, payClosed, nil); err != nil {
|
if err := client.encode(&hdr, payClosed, nil); err != nil {
|
||||||
expLog("error encoding server closed message:", err)
|
expLog("error encoding server closed message:", err)
|
||||||
}
|
}
|
||||||
|
@ -213,8 +213,8 @@ func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, size,
|
|||||||
if dir == Send {
|
if dir == Send {
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; n == -1 || i < n; i++ {
|
for i := 0; n == -1 || i < n; i++ {
|
||||||
val, closed := nch.recv()
|
val, ok := nch.recv()
|
||||||
if closed {
|
if !ok {
|
||||||
if err = imp.encode(hdr, payClosed, nil); err != nil {
|
if err = imp.encode(hdr, payClosed, nil); err != nil {
|
||||||
impLog("error encoding client closed message:", err)
|
impLog("error encoding client closed message:", err)
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,8 @@ func exportReceive(exp *Exporter, t *testing.T, expDone chan bool) {
|
|||||||
t.Fatal("exportReceive:", err)
|
t.Fatal("exportReceive:", err)
|
||||||
}
|
}
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
v := <-ch
|
v, ok := <-ch
|
||||||
if closed(ch) {
|
if !ok {
|
||||||
if i != closeCount {
|
if i != closeCount {
|
||||||
t.Errorf("exportReceive expected close at %d; got one at %d", closeCount, i)
|
t.Errorf("exportReceive expected close at %d; got one at %d", closeCount, i)
|
||||||
}
|
}
|
||||||
@ -78,8 +78,8 @@ func importReceive(imp *Importer, t *testing.T, done chan bool) {
|
|||||||
t.Fatal("importReceive:", err)
|
t.Fatal("importReceive:", err)
|
||||||
}
|
}
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
v := <-ch
|
v, ok := <-ch
|
||||||
if closed(ch) {
|
if !ok {
|
||||||
if i != closeCount {
|
if i != closeCount {
|
||||||
t.Errorf("importReceive expected close at %d; got one at %d", closeCount, i)
|
t.Errorf("importReceive expected close at %d; got one at %d", closeCount, i)
|
||||||
}
|
}
|
||||||
@ -212,8 +212,8 @@ func TestExportHangup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// Now hang up the channel. Importer should see it close.
|
// Now hang up the channel. Importer should see it close.
|
||||||
exp.Hangup("exportedSend")
|
exp.Hangup("exportedSend")
|
||||||
v = <-ich
|
v, ok := <-ich
|
||||||
if !closed(ich) {
|
if ok {
|
||||||
t.Fatal("expected channel to be closed; got value", v)
|
t.Fatal("expected channel to be closed; got value", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,8 +242,8 @@ func TestImportHangup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// Now hang up the channel. Exporter should see it close.
|
// Now hang up the channel. Exporter should see it close.
|
||||||
imp.Hangup("exportedRecv")
|
imp.Hangup("exportedRecv")
|
||||||
v = <-ech
|
v, ok := <-ech
|
||||||
if !closed(ech) {
|
if ok {
|
||||||
t.Fatal("expected channel to be closed; got value", v)
|
t.Fatal("expected channel to be closed; got value", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ func TestInotifyEvents(t *testing.T) {
|
|||||||
// Receive events on the event channel on a separate goroutine
|
// Receive events on the event channel on a separate goroutine
|
||||||
eventstream := watcher.Event
|
eventstream := watcher.Event
|
||||||
var eventsReceived = 0
|
var eventsReceived = 0
|
||||||
|
done := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
for event := range eventstream {
|
for event := range eventstream {
|
||||||
// Only count relevant events
|
// Only count relevant events
|
||||||
@ -45,6 +46,7 @@ func TestInotifyEvents(t *testing.T) {
|
|||||||
t.Logf("unexpected event received: %s", event)
|
t.Logf("unexpected event received: %s", event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
done <- true
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Create a file
|
// Create a file
|
||||||
@ -64,16 +66,12 @@ func TestInotifyEvents(t *testing.T) {
|
|||||||
t.Log("calling Close()")
|
t.Log("calling Close()")
|
||||||
watcher.Close()
|
watcher.Close()
|
||||||
t.Log("waiting for the event channel to become closed...")
|
t.Log("waiting for the event channel to become closed...")
|
||||||
var i = 0
|
select {
|
||||||
for !closed(eventstream) {
|
case <-done:
|
||||||
if i >= 20 {
|
|
||||||
t.Fatal("event stream was not closed after 1 second, as expected")
|
|
||||||
}
|
|
||||||
t.Log("waiting for 50 ms...")
|
|
||||||
time.Sleep(50e6) // 50 ms
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
t.Log("event channel closed")
|
t.Log("event channel closed")
|
||||||
|
case <-time.After(1e9):
|
||||||
|
t.Fatal("event stream was not closed after 1 second")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -968,28 +968,28 @@ func TestChan(t *testing.T) {
|
|||||||
|
|
||||||
// Recv
|
// Recv
|
||||||
c <- 3
|
c <- 3
|
||||||
if i := cv.Recv().(*IntValue).Get(); i != 3 {
|
if i, ok := cv.Recv(); i.(*IntValue).Get() != 3 || !ok {
|
||||||
t.Errorf("native send 3, reflect Recv %d", i)
|
t.Errorf("native send 3, reflect Recv %d, %t", i.(*IntValue).Get(), ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryRecv fail
|
// TryRecv fail
|
||||||
val := cv.TryRecv()
|
val, ok := cv.TryRecv()
|
||||||
if val != nil {
|
if val != nil || ok {
|
||||||
t.Errorf("TryRecv on empty chan: %s", valueToString(val))
|
t.Errorf("TryRecv on empty chan: %s, %t", valueToString(val), ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryRecv success
|
// TryRecv success
|
||||||
c <- 4
|
c <- 4
|
||||||
val = cv.TryRecv()
|
val, ok = cv.TryRecv()
|
||||||
if val == nil {
|
if val == nil {
|
||||||
t.Errorf("TryRecv on ready chan got nil")
|
t.Errorf("TryRecv on ready chan got nil")
|
||||||
} else if i := val.(*IntValue).Get(); i != 4 {
|
} else if i := val.(*IntValue).Get(); i != 4 || !ok {
|
||||||
t.Errorf("native send 4, TryRecv %d", i)
|
t.Errorf("native send 4, TryRecv %d, %t", i, ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrySend fail
|
// TrySend fail
|
||||||
c <- 100
|
c <- 100
|
||||||
ok := cv.TrySend(NewValue(5))
|
ok = cv.TrySend(NewValue(5))
|
||||||
i := <-c
|
i := <-c
|
||||||
if ok {
|
if ok {
|
||||||
t.Errorf("TrySend on full chan succeeded: value %d", i)
|
t.Errorf("TrySend on full chan succeeded: value %d", i)
|
||||||
@ -1008,20 +1008,11 @@ func TestChan(t *testing.T) {
|
|||||||
// Close
|
// Close
|
||||||
c <- 123
|
c <- 123
|
||||||
cv.Close()
|
cv.Close()
|
||||||
if cv.Closed() {
|
if i, ok := cv.Recv(); i.(*IntValue).Get() != 123 || !ok {
|
||||||
t.Errorf("closed too soon - 1")
|
t.Errorf("send 123 then close; Recv %d, %t", i.(*IntValue).Get(), ok)
|
||||||
}
|
}
|
||||||
if i := cv.Recv().(*IntValue).Get(); i != 123 {
|
if i, ok := cv.Recv(); i.(*IntValue).Get() != 0 || ok {
|
||||||
t.Errorf("send 123 then close; Recv %d", i)
|
t.Errorf("after close Recv %d, %t", i.(*IntValue).Get(), ok)
|
||||||
}
|
|
||||||
if cv.Closed() {
|
|
||||||
t.Errorf("closed too soon - 2")
|
|
||||||
}
|
|
||||||
if i := cv.Recv().(*IntValue).Get(); i != 0 {
|
|
||||||
t.Errorf("after close Recv %d", i)
|
|
||||||
}
|
|
||||||
if !cv.Closed() {
|
|
||||||
t.Errorf("not closed")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1032,7 +1023,7 @@ func TestChan(t *testing.T) {
|
|||||||
if cv.TrySend(NewValue(7)) {
|
if cv.TrySend(NewValue(7)) {
|
||||||
t.Errorf("TrySend on sync chan succeeded")
|
t.Errorf("TrySend on sync chan succeeded")
|
||||||
}
|
}
|
||||||
if cv.TryRecv() != nil {
|
if v, ok := cv.TryRecv(); v != nil || ok {
|
||||||
t.Errorf("TryRecv on sync chan succeeded")
|
t.Errorf("TryRecv on sync chan succeeded")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,19 +671,12 @@ func (v *ChanValue) Get() uintptr { return *(*uintptr)(v.addr) }
|
|||||||
|
|
||||||
// implemented in ../pkg/runtime/reflect.cgo
|
// implemented in ../pkg/runtime/reflect.cgo
|
||||||
func makechan(typ *runtime.ChanType, size uint32) (ch *byte)
|
func makechan(typ *runtime.ChanType, size uint32) (ch *byte)
|
||||||
func chansend(ch, val *byte, pres *bool)
|
func chansend(ch, val *byte, selected *bool)
|
||||||
func chanrecv(ch, val *byte, pres *bool)
|
func chanrecv(ch, val *byte, selected *bool, ok *bool)
|
||||||
func chanclosed(ch *byte) bool
|
|
||||||
func chanclose(ch *byte)
|
func chanclose(ch *byte)
|
||||||
func chanlen(ch *byte) int32
|
func chanlen(ch *byte) int32
|
||||||
func chancap(ch *byte) int32
|
func chancap(ch *byte) int32
|
||||||
|
|
||||||
// Closed returns the result of closed(c) on the underlying channel.
|
|
||||||
func (v *ChanValue) Closed() bool {
|
|
||||||
ch := *(**byte)(v.addr)
|
|
||||||
return chanclosed(ch)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the channel.
|
// Close closes the channel.
|
||||||
func (v *ChanValue) Close() {
|
func (v *ChanValue) Close() {
|
||||||
ch := *(**byte)(v.addr)
|
ch := *(**byte)(v.addr)
|
||||||
@ -700,52 +693,61 @@ func (v *ChanValue) Cap() int {
|
|||||||
return int(chancap(ch))
|
return int(chancap(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal send; non-blocking if b != nil
|
// internal send; non-blocking if selected != nil
|
||||||
func (v *ChanValue) send(x Value, b *bool) {
|
func (v *ChanValue) send(x Value, selected *bool) {
|
||||||
t := v.Type().(*ChanType)
|
t := v.Type().(*ChanType)
|
||||||
if t.Dir()&SendDir == 0 {
|
if t.Dir()&SendDir == 0 {
|
||||||
panic("send on recv-only channel")
|
panic("send on recv-only channel")
|
||||||
}
|
}
|
||||||
typesMustMatch(t.Elem(), x.Type())
|
typesMustMatch(t.Elem(), x.Type())
|
||||||
ch := *(**byte)(v.addr)
|
ch := *(**byte)(v.addr)
|
||||||
chansend(ch, (*byte)(x.getAddr()), b)
|
chansend(ch, (*byte)(x.getAddr()), selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal recv; non-blocking if b != nil
|
// internal recv; non-blocking if selected != nil
|
||||||
func (v *ChanValue) recv(b *bool) Value {
|
func (v *ChanValue) recv(selected *bool) (Value, bool) {
|
||||||
t := v.Type().(*ChanType)
|
t := v.Type().(*ChanType)
|
||||||
if t.Dir()&RecvDir == 0 {
|
if t.Dir()&RecvDir == 0 {
|
||||||
panic("recv on send-only channel")
|
panic("recv on send-only channel")
|
||||||
}
|
}
|
||||||
ch := *(**byte)(v.addr)
|
ch := *(**byte)(v.addr)
|
||||||
x := MakeZero(t.Elem())
|
x := MakeZero(t.Elem())
|
||||||
chanrecv(ch, (*byte)(x.getAddr()), b)
|
var ok bool
|
||||||
return x
|
chanrecv(ch, (*byte)(x.getAddr()), selected, &ok)
|
||||||
|
return x, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send sends x on the channel v.
|
// Send sends x on the channel v.
|
||||||
func (v *ChanValue) Send(x Value) { v.send(x, nil) }
|
func (v *ChanValue) Send(x Value) { v.send(x, nil) }
|
||||||
|
|
||||||
// Recv receives and returns a value from the channel v.
|
// Recv receives and returns a value from the channel v.
|
||||||
func (v *ChanValue) Recv() Value { return v.recv(nil) }
|
// The receive blocks until a value is ready.
|
||||||
|
// The boolean value ok is true if the value x corresponds to a send
|
||||||
|
// on the channel, false if it is a zero value received because the channel is closed.
|
||||||
|
func (v *ChanValue) Recv() (x Value, ok bool) {
|
||||||
|
return v.recv(nil)
|
||||||
|
}
|
||||||
|
|
||||||
// TrySend attempts to sends x on the channel v but will not block.
|
// TrySend attempts to sends x on the channel v but will not block.
|
||||||
// It returns true if the value was sent, false otherwise.
|
// It returns true if the value was sent, false otherwise.
|
||||||
func (v *ChanValue) TrySend(x Value) bool {
|
func (v *ChanValue) TrySend(x Value) bool {
|
||||||
var ok bool
|
var selected bool
|
||||||
v.send(x, &ok)
|
v.send(x, &selected)
|
||||||
return ok
|
return selected
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryRecv attempts to receive a value from the channel v but will not block.
|
// TryRecv attempts to receive a value from the channel v but will not block.
|
||||||
// It returns the value if one is received, nil otherwise.
|
// If the receive cannot finish without blocking, TryRecv instead returns x == nil.
|
||||||
func (v *ChanValue) TryRecv() Value {
|
// If the receive can finish without blocking, TryRecv returns x != nil.
|
||||||
var ok bool
|
// The boolean value ok is true if the value x corresponds to a send
|
||||||
x := v.recv(&ok)
|
// on the channel, false if it is a zero value received because the channel is closed.
|
||||||
if !ok {
|
func (v *ChanValue) TryRecv() (x Value, ok bool) {
|
||||||
return nil
|
var selected bool
|
||||||
|
x, ok = v.recv(&selected)
|
||||||
|
if !selected {
|
||||||
|
return nil, false
|
||||||
}
|
}
|
||||||
return x
|
return x, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeChan creates a new channel with the specified type and buffer size.
|
// MakeChan creates a new channel with the specified type and buffer size.
|
||||||
|
@ -896,8 +896,8 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) {
|
|||||||
}
|
}
|
||||||
} else if ch := iter(field); ch != nil {
|
} else if ch := iter(field); ch != nil {
|
||||||
for {
|
for {
|
||||||
e := ch.Recv()
|
e, ok := ch.Recv()
|
||||||
if ch.Closed() {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
loopBody(st.clone(e))
|
loopBody(st.clone(e))
|
||||||
|
@ -306,8 +306,8 @@ func recvValues(multiplex chan<- interface{}, channel interface{}) {
|
|||||||
c := reflect.NewValue(channel).(*reflect.ChanValue)
|
c := reflect.NewValue(channel).(*reflect.ChanValue)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
v := c.Recv()
|
v, ok := c.Recv()
|
||||||
if c.Closed() {
|
if !ok {
|
||||||
multiplex <- channelClosed{channel}
|
multiplex <- channelClosed{channel}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -22,21 +22,18 @@ func main() {
|
|||||||
|
|
||||||
c <- 0 // ok
|
c <- 0 // ok
|
||||||
<-c // ok
|
<-c // ok
|
||||||
//TODO(rsc): uncomment when this syntax is valid for receive+check closed
|
x, ok := <-c // ok
|
||||||
// x, ok := <-c // ok
|
_, _ = x, ok
|
||||||
// _, _ = x, ok
|
|
||||||
|
|
||||||
cr <- 0 // ERROR "send"
|
cr <- 0 // ERROR "send"
|
||||||
<-cr // ok
|
<-cr // ok
|
||||||
//TODO(rsc): uncomment when this syntax is valid for receive+check closed
|
x, ok = <-cr // ok
|
||||||
// x, ok = <-cr // ok
|
_, _ = x, ok
|
||||||
// _, _ = x, ok
|
|
||||||
|
|
||||||
cs <- 0 // ok
|
cs <- 0 // ok
|
||||||
<-cs // ERROR "receive"
|
<-cs // ERROR "receive"
|
||||||
////TODO(rsc): uncomment when this syntax is valid for receive+check closed
|
x, ok = <-cs // ERROR "receive"
|
||||||
//// x, ok = <-cs // ERROR "receive"
|
_, _ = x, ok
|
||||||
//// _, _ = x, ok
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case c <- 0: // ok
|
case c <- 0: // ok
|
||||||
|
@ -88,12 +88,16 @@ func main() {
|
|||||||
ch <- 7
|
ch <- 7
|
||||||
})
|
})
|
||||||
|
|
||||||
// receiving (a small number of times) from a closed channel never blocks
|
// receiving from a closed channel never blocks
|
||||||
testBlock(never, func() {
|
testBlock(never, func() {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
if <-closedch != 0 {
|
if <-closedch != 0 {
|
||||||
panic("expected zero value when reading from closed channel")
|
panic("expected zero value when reading from closed channel")
|
||||||
}
|
}
|
||||||
|
if x, ok := <-closedch; x != 0 || ok {
|
||||||
|
println("closedch:", x, ok)
|
||||||
|
panic("expected 0, false from closed channel")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -191,6 +195,18 @@ func main() {
|
|||||||
case <-closedch:
|
case <-closedch:
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
testBlock(never, func() {
|
||||||
|
select {
|
||||||
|
case x := <-closedch:
|
||||||
|
_ = x
|
||||||
|
}
|
||||||
|
})
|
||||||
|
testBlock(never, func() {
|
||||||
|
select {
|
||||||
|
case x, ok := <-closedch:
|
||||||
|
_, _ = x, ok
|
||||||
|
}
|
||||||
|
})
|
||||||
testPanic(always, func() {
|
testPanic(always, func() {
|
||||||
select {
|
select {
|
||||||
case closedch <- 7:
|
case closedch <- 7:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Test close(c), closed(c).
|
// Test close(c), receive of closed channel.
|
||||||
//
|
//
|
||||||
// TODO(rsc): Doesn't check behavior of close(c) when there
|
// TODO(rsc): Doesn't check behavior of close(c) when there
|
||||||
// are blocked senders/receivers.
|
// are blocked senders/receivers.
|
||||||
@ -14,10 +14,11 @@ package main
|
|||||||
type Chan interface {
|
type Chan interface {
|
||||||
Send(int)
|
Send(int)
|
||||||
Nbsend(int) bool
|
Nbsend(int) bool
|
||||||
Recv() int
|
Recv() (int)
|
||||||
Nbrecv() (int, bool)
|
Nbrecv() (int, bool)
|
||||||
|
Recv2() (int, bool)
|
||||||
|
Nbrecv2() (int, bool, bool)
|
||||||
Close()
|
Close()
|
||||||
Closed() bool
|
|
||||||
Impl() string
|
Impl() string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,12 +53,23 @@ func (c XChan) Nbrecv() (int, bool) {
|
|||||||
panic("nbrecv")
|
panic("nbrecv")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c XChan) Close() {
|
func (c XChan) Recv2() (int, bool) {
|
||||||
close(c)
|
x, ok := <-c
|
||||||
|
return x, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c XChan) Closed() bool {
|
func (c XChan) Nbrecv2() (int, bool, bool) {
|
||||||
return closed(c)
|
select {
|
||||||
|
case x, ok := <-c:
|
||||||
|
return x, ok, true
|
||||||
|
default:
|
||||||
|
return 0, false, false
|
||||||
|
}
|
||||||
|
panic("nbrecv2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c XChan) Close() {
|
||||||
|
close(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c XChan) Impl() string {
|
func (c XChan) Impl() string {
|
||||||
@ -101,12 +113,26 @@ func (c SChan) Nbrecv() (int, bool) {
|
|||||||
panic("nbrecv")
|
panic("nbrecv")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c SChan) Close() {
|
func (c SChan) Recv2() (int, bool) {
|
||||||
close(c)
|
select {
|
||||||
|
case x, ok := <-c:
|
||||||
|
return x, ok
|
||||||
|
}
|
||||||
|
panic("recv")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c SChan) Closed() bool {
|
func (c SChan) Nbrecv2() (int, bool, bool) {
|
||||||
return closed(c)
|
select {
|
||||||
|
default:
|
||||||
|
return 0, false, false
|
||||||
|
case x, ok := <-c:
|
||||||
|
return x, ok, true
|
||||||
|
}
|
||||||
|
panic("nbrecv")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c SChan) Close() {
|
||||||
|
close(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c SChan) Impl() string {
|
func (c SChan) Impl() string {
|
||||||
@ -156,12 +182,28 @@ func (c SSChan) Nbrecv() (int, bool) {
|
|||||||
panic("nbrecv")
|
panic("nbrecv")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c SSChan) Close() {
|
func (c SSChan) Recv2() (int, bool) {
|
||||||
close(c)
|
select {
|
||||||
|
case <-dummy:
|
||||||
|
case x, ok := <-c:
|
||||||
|
return x, ok
|
||||||
|
}
|
||||||
|
panic("recv")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c SSChan) Closed() bool {
|
func (c SSChan) Nbrecv2() (int, bool, bool) {
|
||||||
return closed(c)
|
select {
|
||||||
|
case <-dummy:
|
||||||
|
default:
|
||||||
|
return 0, false, false
|
||||||
|
case x, ok := <-c:
|
||||||
|
return x, ok, true
|
||||||
|
}
|
||||||
|
panic("nbrecv")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c SSChan) Close() {
|
||||||
|
close(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c SSChan) Impl() string {
|
func (c SSChan) Impl() string {
|
||||||
@ -179,29 +221,23 @@ func shouldPanic(f func()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func test1(c Chan) {
|
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++ {
|
for i := 0; i < 3; i++ {
|
||||||
// recv a close signal (a zero value)
|
// recv a close signal (a zero value)
|
||||||
if x := c.Recv(); x != 0 {
|
if x := c.Recv(); x != 0 {
|
||||||
println("test1: recv on closed got non-zero:", x, c.Impl())
|
println("test1: recv on closed:", x, c.Impl())
|
||||||
|
}
|
||||||
|
if x, ok := c.Recv2(); x != 0 || ok {
|
||||||
|
println("test1: recv2 on closed:", x, ok, c.Impl())
|
||||||
}
|
}
|
||||||
|
|
||||||
// should now be closed.
|
// should work with select: received a value without blocking, so selected == true.
|
||||||
if !c.Closed() {
|
x, selected := c.Nbrecv()
|
||||||
println("test1: not closed after recv zero", c.Impl())
|
if x != 0 || !selected {
|
||||||
|
println("test1: recv on closed nb:", x, selected, c.Impl())
|
||||||
}
|
}
|
||||||
|
x, ok, selected := c.Nbrecv2()
|
||||||
// should work with ,ok: received a value without blocking, so ok == true.
|
if x != 0 || ok || !selected {
|
||||||
x, ok := c.Nbrecv()
|
println("test1: recv2 on closed nb:", x, ok, selected, c.Impl())
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,11 +257,6 @@ func test1(c Chan) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testasync1(c Chan) {
|
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
|
// should be able to get the last value via Recv
|
||||||
if x := c.Recv(); x != 1 {
|
if x := c.Recv(); x != 1 {
|
||||||
println("testasync1: Recv did not get 1:", x, c.Impl())
|
println("testasync1: Recv did not get 1:", x, c.Impl())
|
||||||
@ -235,19 +266,31 @@ func testasync1(c Chan) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testasync2(c Chan) {
|
func testasync2(c Chan) {
|
||||||
// not closed until the close signal (a zero value) has been received.
|
// should be able to get the last value via Recv2
|
||||||
if c.Closed() {
|
if x, ok := c.Recv2(); x != 1 || !ok {
|
||||||
println("testasync2: Closed before Recv zero:", c.Impl())
|
println("testasync1: Recv did not get 1, true:", x, ok, c.Impl())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test1(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testasync3(c Chan) {
|
||||||
// should be able to get the last value via Nbrecv
|
// should be able to get the last value via Nbrecv
|
||||||
if x, ok := c.Nbrecv(); !ok || x != 1 {
|
if x, selected := c.Nbrecv(); x != 1 || !selected {
|
||||||
println("testasync2: Nbrecv did not get 1, true:", x, ok, c.Impl())
|
println("testasync2: Nbrecv did not get 1, true:", x, selected, c.Impl())
|
||||||
}
|
}
|
||||||
|
|
||||||
test1(c)
|
test1(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testasync4(c Chan) {
|
||||||
|
// should be able to get the last value via Nbrecv2
|
||||||
|
if x, ok, selected := c.Nbrecv2(); x != 1 || !ok || !selected {
|
||||||
|
println("testasync2: Nbrecv did not get 1, true, true:", x, ok, selected, c.Impl())
|
||||||
|
}
|
||||||
|
test1(c)
|
||||||
|
}
|
||||||
|
|
||||||
func closedsync() chan int {
|
func closedsync() chan int {
|
||||||
c := make(chan int)
|
c := make(chan int)
|
||||||
close(c)
|
close(c)
|
||||||
@ -261,15 +304,27 @@ func closedasync() chan int {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
var mks = []func(chan int) Chan {
|
||||||
test1(XChan(closedsync()))
|
func(c chan int) Chan { return XChan(c) },
|
||||||
test1(SChan(closedsync()))
|
func(c chan int) Chan { return SChan(c) },
|
||||||
test1(SSChan(closedsync()))
|
func(c chan int) Chan { return SSChan(c) },
|
||||||
|
}
|
||||||
testasync1(XChan(closedasync()))
|
|
||||||
testasync1(SChan(closedasync()))
|
var testcloseds = []func(Chan) {
|
||||||
testasync1(SSChan(closedasync()))
|
testasync1,
|
||||||
testasync2(XChan(closedasync()))
|
testasync2,
|
||||||
testasync2(SChan(closedasync()))
|
testasync3,
|
||||||
testasync2(SSChan(closedasync()))
|
testasync4,
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, mk := range mks {
|
||||||
|
test1(mk(closedsync()))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testclosed := range testcloseds {
|
||||||
|
for _, mk := range mks {
|
||||||
|
testclosed(mk(closedasync()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ func bad(args ...int) {
|
|||||||
ch := make(chan int)
|
ch := make(chan int)
|
||||||
close(ch...) // ERROR "[.][.][.]"
|
close(ch...) // ERROR "[.][.][.]"
|
||||||
_ = len(args...) // ERROR "[.][.][.]"
|
_ = len(args...) // ERROR "[.][.][.]"
|
||||||
_ = closed(ch...) // ERROR "[.][.][.]"
|
|
||||||
_ = new(int...) // ERROR "[.][.][.]"
|
_ = new(int...) // ERROR "[.][.][.]"
|
||||||
n := 10
|
n := 10
|
||||||
_ = make([]byte, n...) // ERROR "[.][.][.]"
|
_ = make([]byte, n...) // ERROR "[.][.][.]"
|
||||||
|
@ -43,10 +43,6 @@ func main() {
|
|||||||
_, b = m[2] // ERROR "cannot .* bool.*type Bool"
|
_, b = m[2] // ERROR "cannot .* bool.*type Bool"
|
||||||
m[2] = 1, b // ERROR "cannot use.*type Bool.*as type bool"
|
m[2] = 1, b // ERROR "cannot use.*type Bool.*as type bool"
|
||||||
|
|
||||||
////TODO(rsc): uncomment when this syntax is valid for receive+check closed
|
|
||||||
//// _, b = <-c // ERROR "cannot .* bool.*type Bool"
|
|
||||||
//// _ = b
|
|
||||||
|
|
||||||
var inter interface{}
|
var inter interface{}
|
||||||
_, b = inter.(Map) // ERROR "cannot .* bool.*type Bool"
|
_, b = inter.(Map) // ERROR "cannot .* bool.*type Bool"
|
||||||
_ = b
|
_ = b
|
||||||
@ -57,8 +53,9 @@ func main() {
|
|||||||
_, b = minter.(Map) // ERROR "cannot .* bool.*type Bool"
|
_, b = minter.(Map) // ERROR "cannot .* bool.*type Bool"
|
||||||
_ = b
|
_ = b
|
||||||
|
|
||||||
asBool(closed(c)) // ERROR "cannot use.*type bool.*as type Bool"
|
_, bb := <-c
|
||||||
b = closed(c) // ERROR "cannot use.*type bool.*type Bool"
|
asBool(bb) // ERROR "cannot use.*type bool.*as type Bool"
|
||||||
|
_, b = <-c // ERROR "cannot .* bool.*type Bool"
|
||||||
_ = b
|
_ = b
|
||||||
|
|
||||||
asString(String(slice)) // ERROR "cannot .*type Slice.*type String"
|
asString(String(slice)) // ERROR "cannot .*type Slice.*type String"
|
||||||
|
Loading…
Reference in New Issue
Block a user