summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-08-26 10:47:18 -0700
committerRuss Cox <rsc@golang.org>2009-08-26 10:47:18 -0700
commitea40944a877af0851eb56349ba9ad1e41396ea54 (patch)
treeac488031c2ac65930e9fef6cde4ff196b5a7247b
parentcb1a4626c90831f20decda3089cc04673ad9609b (diff)
downloadgolang-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.go19
-rw-r--r--src/pkg/reflect/value.go14
-rw-r--r--src/pkg/runtime/chan.c18
-rw-r--r--src/pkg/runtime/reflect.cgo8
-rw-r--r--src/pkg/runtime/runtime.h4
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*);