diff options
Diffstat (limited to 'src/pkg/io/pipe.go')
-rw-r--r-- | src/pkg/io/pipe.go | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/src/pkg/io/pipe.go b/src/pkg/io/pipe.go index 00be8efa2..f3f0f1757 100644 --- a/src/pkg/io/pipe.go +++ b/src/pkg/io/pipe.go @@ -8,13 +8,16 @@ package io import ( - "os" + "errors" "sync" ) +// ErrClosedPipe is the error used for read or write operations on a closed pipe. +var ErrClosedPipe = errors.New("io: read/write on closed pipe") + type pipeResult struct { n int - err os.Error + err error } // A pipe is the shared pipe structure underlying PipeReader and PipeWriter. @@ -25,11 +28,11 @@ type pipe struct { data []byte // data remaining in pending write rwait sync.Cond // waiting reader wwait sync.Cond // waiting writer - rerr os.Error // if reader closed, error to give writes - werr os.Error // if writer closed, error to give reads + rerr error // if reader closed, error to give writes + werr error // if writer closed, error to give reads } -func (p *pipe) read(b []byte) (n int, err os.Error) { +func (p *pipe) read(b []byte) (n int, err error) { // One reader at a time. p.rl.Lock() defer p.rl.Unlock() @@ -38,7 +41,7 @@ func (p *pipe) read(b []byte) (n int, err os.Error) { defer p.l.Unlock() for { if p.rerr != nil { - return 0, os.EINVAL + return 0, ErrClosedPipe } if p.data != nil { break @@ -59,7 +62,7 @@ func (p *pipe) read(b []byte) (n int, err os.Error) { var zero [0]byte -func (p *pipe) write(b []byte) (n int, err os.Error) { +func (p *pipe) write(b []byte) (n int, err error) { // pipe uses nil to mean not available if b == nil { b = zero[:] @@ -82,7 +85,7 @@ func (p *pipe) write(b []byte) (n int, err os.Error) { break } if p.werr != nil { - err = os.EINVAL + err = ErrClosedPipe } p.wwait.Wait() } @@ -91,9 +94,9 @@ func (p *pipe) write(b []byte) (n int, err os.Error) { return } -func (p *pipe) rclose(err os.Error) { +func (p *pipe) rclose(err error) { if err == nil { - err = os.EPIPE + err = ErrClosedPipe } p.l.Lock() defer p.l.Unlock() @@ -102,9 +105,9 @@ func (p *pipe) rclose(err os.Error) { p.wwait.Signal() } -func (p *pipe) wclose(err os.Error) { +func (p *pipe) wclose(err error) { if err == nil { - err = os.EOF + err = EOF } p.l.Lock() defer p.l.Unlock() @@ -122,20 +125,20 @@ type PipeReader struct { // it reads data from the pipe, blocking until a writer // arrives or the write end is closed. // If the write end is closed with an error, that error is -// returned as err; otherwise err is os.EOF. -func (r *PipeReader) Read(data []byte) (n int, err os.Error) { +// returned as err; otherwise err is EOF. +func (r *PipeReader) Read(data []byte) (n int, err error) { return r.p.read(data) } // Close closes the reader; subsequent writes to the -// write half of the pipe will return the error os.EPIPE. -func (r *PipeReader) Close() os.Error { +// write half of the pipe will return the error ErrClosedPipe. +func (r *PipeReader) Close() error { return r.CloseWithError(nil) } // CloseWithError closes the reader; subsequent writes // to the write half of the pipe will return the error err. -func (r *PipeReader) CloseWithError(err os.Error) os.Error { +func (r *PipeReader) CloseWithError(err error) error { r.p.rclose(err) return nil } @@ -149,20 +152,20 @@ type PipeWriter struct { // it writes data to the pipe, blocking until readers // have consumed all the data or the read end is closed. // If the read end is closed with an error, that err is -// returned as err; otherwise err is os.EPIPE. -func (w *PipeWriter) Write(data []byte) (n int, err os.Error) { +// returned as err; otherwise err is ErrClosedPipe. +func (w *PipeWriter) Write(data []byte) (n int, err error) { return w.p.write(data) } // Close closes the writer; subsequent reads from the -// read half of the pipe will return no bytes and os.EOF. -func (w *PipeWriter) Close() os.Error { +// read half of the pipe will return no bytes and EOF. +func (w *PipeWriter) Close() error { return w.CloseWithError(nil) } // CloseWithError closes the writer; subsequent reads from the // read half of the pipe will return no bytes and the error err. -func (w *PipeWriter) CloseWithError(err os.Error) os.Error { +func (w *PipeWriter) CloseWithError(err error) error { w.p.wclose(err) return nil } @@ -172,6 +175,10 @@ func (w *PipeWriter) CloseWithError(err os.Error) os.Error { // with code expecting an io.Writer. // Reads on one end are matched with writes on the other, // copying data directly between the two; there is no internal buffering. +// It is safe to call Read and Write in parallel with each other or with +// Close. Close will complete once pending I/O is done. Parallel calls to +// Read, and parallel calls to Write, are also safe: +// the individual calls will be gated sequentially. func Pipe() (*PipeReader, *PipeWriter) { p := new(pipe) p.rwait.L = &p.l |