Commit 1ffb1f2b authored by Rob Pike's avatar Rob Pike

netchan: add new method Hangup to terminate transmission on a channel

Fixes #1151.

R=rsc
CC=golang-dev
https://golang.org/cl/2469043
parent e9c35ac5
...@@ -346,3 +346,19 @@ func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error { ...@@ -346,3 +346,19 @@ func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error {
exp.chans[name] = &chanDir{ch, dir} exp.chans[name] = &chanDir{ch, dir}
return nil return nil
} }
// Hangup disassociates the named channel from the Exporter and closes
// the channel. Messages in flight for the channel may be dropped.
func (exp *Exporter) Hangup(name string) os.Error {
exp.mu.Lock()
chDir, ok := exp.chans[name]
if ok {
exp.chans[name] = nil, false
}
exp.mu.Unlock()
if !ok {
return os.ErrorString("netchan export: hangup: no such channel: " + name)
}
chDir.ch.Close()
return nil
}
...@@ -203,3 +203,19 @@ func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, n int) ...@@ -203,3 +203,19 @@ func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, n int)
} }
return nil return nil
} }
// Hangup disassociates the named channel from the Importer and closes
// the channel. Messages in flight for the channel may be dropped.
func (imp *Importer) Hangup(name string) os.Error {
imp.chanLock.Lock()
chDir, ok := imp.chans[name]
if ok {
imp.chans[name] = nil, false
}
imp.chanLock.Unlock()
if !ok {
return os.ErrorString("netchan import: hangup: no such channel: " + name)
}
chDir.ch.Close()
return nil
}
...@@ -230,12 +230,86 @@ func TestExportSync(t *testing.T) { ...@@ -230,12 +230,86 @@ func TestExportSync(t *testing.T) {
<-done <-done
} }
// Test hanging up the send side of an export.
// TODO: test hanging up the receive side of an export.
func TestExportHangup(t *testing.T) {
exp, err := NewExporter("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal("new exporter:", err)
}
imp, err := NewImporter("tcp", exp.Addr().String())
if err != nil {
t.Fatal("new importer:", err)
}
ech := make(chan int)
err = exp.Export("exportedSend", ech, Send)
if err != nil {
t.Fatal("export:", err)
}
// Prepare to receive two values. We'll actually deliver only one.
ich := make(chan int)
err = imp.ImportNValues("exportedSend", ich, Recv, 2)
if err != nil {
t.Fatal("import exportedSend:", err)
}
// Send one value, receive it.
const Value = 1234
ech <- Value
v := <-ich
if v != Value {
t.Fatal("expected", Value, "got", v)
}
// Now hang up the channel. Importer should see it close.
exp.Hangup("exportedSend")
v = <-ich
if !closed(ich) {
t.Fatal("expected channel to be closed; got value", v)
}
}
// Test hanging up the send side of an import.
// TODO: test hanging up the receive side of an import.
func TestImportHangup(t *testing.T) {
exp, err := NewExporter("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal("new exporter:", err)
}
imp, err := NewImporter("tcp", exp.Addr().String())
if err != nil {
t.Fatal("new importer:", err)
}
ech := make(chan int)
err = exp.Export("exportedRecv", ech, Recv)
if err != nil {
t.Fatal("export:", err)
}
// Prepare to Send two values. We'll actually deliver only one.
ich := make(chan int)
err = imp.ImportNValues("exportedRecv", ich, Send, 2)
if err != nil {
t.Fatal("import exportedRecv:", err)
}
// Send one value, receive it.
const Value = 1234
ich <- Value
v := <-ech
if v != Value {
t.Fatal("expected", Value, "got", v)
}
// Now hang up the channel. Exporter should see it close.
imp.Hangup("exportedRecv")
v = <-ech
if !closed(ech) {
t.Fatal("expected channel to be closed; got value", v)
}
}
// This test cross-connects a pair of exporter/importer pairs.
type value struct { type value struct {
i int i int
source string source string
} }
// This test cross-connects a pair of exporter/importer pairs.
func TestCrossConnect(t *testing.T) { func TestCrossConnect(t *testing.T) {
e1, err := NewExporter("tcp", "127.0.0.1:0") e1, err := NewExporter("tcp", "127.0.0.1:0")
if err != nil { if err != nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment