diff options
author | Russ Cox <rsc@golang.org> | 2009-08-26 10:47:18 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2009-08-26 10:47:18 -0700 |
commit | ea40944a877af0851eb56349ba9ad1e41396ea54 (patch) | |
tree | ac488031c2ac65930e9fef6cde4ff196b5a7247b | |
parent | cb1a4626c90831f20decda3089cc04673ad9609b (diff) | |
download | golang-ea40944a877af0851eb56349ba9ad1e41396ea54.tar.gz |
add Close() and Closed() to ChanValue
R=r
DELTA=60 (56 added, 3 deleted, 1 changed)
OCL=33868
CL=33872
-rw-r--r-- | src/pkg/reflect/all_test.go | 19 | ||||
-rw-r--r-- | src/pkg/reflect/value.go | 14 | ||||
-rw-r--r-- | src/pkg/runtime/chan.c | 18 | ||||
-rw-r--r-- | src/pkg/runtime/reflect.cgo | 8 | ||||
-rw-r--r-- | src/pkg/runtime/runtime.h | 4 |
5 files changed, 58 insertions, 5 deletions
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go index 5f0211c6a..3a1c220da 100644 --- a/src/pkg/reflect/all_test.go +++ b/src/pkg/reflect/all_test.go @@ -726,6 +726,25 @@ func TestChan(t *testing.T) { t.Errorf("TrySend 6, recv %d", i); } } + + // Close + c <- 123; + cv.Close(); + if cv.Closed() { + t.Errorf("closed too soon - 1"); + } + if i := cv.Recv().(*IntValue).Get(); i != 123 { + t.Errorf("send 123 then close; Recv %d", i); + } + 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"); + } } // check creation of unbuffered channel diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go index e2df30b79..daa3f11ba 100644 --- a/src/pkg/reflect/value.go +++ b/src/pkg/reflect/value.go @@ -634,6 +634,20 @@ func (v *ChanValue) Get() uintptr { func makechan(typ *runtime.ChanType, size uint32) (ch *byte) func chansend(ch, val *byte, pres *bool) func chanrecv(ch, val *byte, pres *bool) +func chanclosed(ch *byte) bool +func chanclose(ch *byte) + +// 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. +func (v *ChanValue) Close() { + ch := *(**byte)(v.addr); + chanclose(ch); +} // internal send; non-blocking if b != nil func (v *ChanValue) send(x Value, b *bool) { diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c index ceebebf8b..00d020749 100644 --- a/src/pkg/runtime/chan.c +++ b/src/pkg/runtime/chan.c @@ -905,14 +905,24 @@ sys·closechan(Hchan *c) unlock(&chanlock); } +void +chanclose(Hchan *c) +{ + sys·closechan(c); +} + +bool +chanclosed(Hchan *c) +{ + return (c->closed & Rclosed) != 0; +} + + // closedchan(sel *byte) bool; void sys·closedchan(Hchan *c, bool closed) { - // test Rclosed - closed = 0; - if(c->closed & Rclosed) - closed = 1; + closed = chanclosed(c); FLUSH(&closed); } diff --git a/src/pkg/runtime/reflect.cgo b/src/pkg/runtime/reflect.cgo index 016b9e9ec..81c1d4a12 100644 --- a/src/pkg/runtime/reflect.cgo +++ b/src/pkg/runtime/reflect.cgo @@ -78,6 +78,14 @@ func chanrecv(ch *byte, val *byte, pres *bool) { chanrecv((Hchan*)ch, val, pres); } +func chanclose(ch *byte) { + chanclose((Hchan*)ch); +} + +func chanclosed(ch *byte) (r bool) { + r = chanclosed((Hchan*)ch); +} + /* * Go wrappers around the functions in iface.c diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index c346c692f..1e89a4578 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -73,7 +73,7 @@ typedef struct Hchan Hchan; * amd64: allocated downwards from R15 * x86: allocated upwards from 0(FS) * arm: allocated upwards from R9 - * + * * every C file linked into a Go program must include runtime.h * so that the C compiler knows to avoid other uses of these registers. * the Go compilers know to avoid them. @@ -491,5 +491,7 @@ Hmap* makemap(uint32, uint32, uint32, uint32, uint32); Hchan* makechan(uint32, uint32, uint32); void chansend(Hchan*, void*, bool*); void chanrecv(Hchan*, void*, bool*); +void chanclose(Hchan*); +bool chanclosed(Hchan*); void ifaceE2I(struct InterfaceType*, Eface, Iface*); |