diff options
| author | Russ Cox <rsc@golang.org> | 2009-05-22 22:42:12 -0700 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2009-05-22 22:42:12 -0700 |
| commit | 2a4dcfffc9d0618dd63b04db50816d82e4db5dc7 (patch) | |
| tree | 663f9c896bbee9961732b93a4b987cebff4f5199 /src/lib/io | |
| parent | b112d42ad60551a075d0bf4c06667f11e7aa976d (diff) | |
| download | go-2a4dcfffc9d0618dd63b04db50816d82e4db5dc7.tar.xz | |
simplifying grammar: delete LBASETYPE and LACONST
R=ken
OCL=29300
CL=29302
Diffstat (limited to 'src/lib/io')
| -rw-r--r-- | src/lib/io/io.go | 14 | ||||
| -rw-r--r-- | src/lib/io/pipe.go | 86 |
2 files changed, 73 insertions, 27 deletions
diff --git a/src/lib/io/io.go b/src/lib/io/io.go index c120d8d443..68ef8c4803 100644 --- a/src/lib/io/io.go +++ b/src/lib/io/io.go @@ -69,7 +69,19 @@ type ReadWriteCloser interface { Closer; } -// Convert a string to an array of bytes for easy marshaling. +// ReadByter is the interface that wraps the basic ReadByte method. +// Implementations of ReadByte typically use buffered I/O. +type ReadByter interface { + ReadByte() (byte, os.Error); +} + +// WriteByter is the interface that wraps the basic WriteByte method. +// Implementations of WriteByte typically use buffered I/O. +type WriteByter interface { + WriteByte(byte) os.Error; +} + +// StringBytes converts a string to an array of bytes for easy marshaling. func StringBytes(s string) []byte { b := make([]byte, len(s)); for i := 0; i < len(s); i++ { diff --git a/src/lib/io/pipe.go b/src/lib/io/pipe.go index 5f9e7a488c..f91bf34567 100644 --- a/src/lib/io/pipe.go +++ b/src/lib/io/pipe.go @@ -21,7 +21,9 @@ type pipeReturn struct { // Shared pipe structure. type pipe struct { rclosed bool; // Read end closed? + rerr os.Error; // Error supplied to CloseReader wclosed bool; // Write end closed? + werr os.Error; // Error supplied to CloseWriter wpend []byte; // Written data waiting to be read. wtot int; // Bytes consumed so far in current write. cr chan []byte; // Write sends data here... @@ -39,7 +41,7 @@ func (p *pipe) Read(data []byte) (n int, err os.Error) { p.wpend = <-p.cr; } if p.wpend == nil { - return 0, nil; + return 0, p.werr; } p.wtot = 0; } @@ -70,7 +72,7 @@ func (p *pipe) Write(data []byte) (n int, err os.Error) { return 0, os.EINVAL; } if p.rclosed { - return 0, os.EPIPE; + return 0, p.rerr; } // Send data to reader. @@ -81,29 +83,34 @@ func (p *pipe) Write(data []byte) (n int, err os.Error) { return res.n, res.err; } -func (p *pipe) CloseReader() os.Error { +func (p *pipe) CloseReader(rerr os.Error) os.Error { if p == nil || p.rclosed { return os.EINVAL; } // Stop any future writes. p.rclosed = true; + if rerr == nil { + rerr = os.EPIPE; + } + p.rerr = rerr; // Stop the current write. if !p.wclosed { - p.cw <- pipeReturn{p.wtot, os.EPIPE}; + p.cw <- pipeReturn{p.wtot, rerr}; } return nil; } -func (p *pipe) CloseWriter() os.Error { +func (p *pipe) CloseWriter(werr os.Error) os.Error { if p == nil || p.wclosed { return os.EINVAL; } // Stop any future reads. p.wclosed = true; + p.werr = werr; // Stop the current read. if !p.rclosed { @@ -121,70 +128,97 @@ func (p *pipe) CloseWriter() os.Error { // 2. Clients cannot use interface conversions on the // read end to find the Write method, and vice versa. -// Read half of pipe. -type pipeRead struct { +// A PipeReader is the read half of a pipe. +type PipeReader struct { lock sync.Mutex; p *pipe; } -func (r *pipeRead) Read(data []byte) (n int, err os.Error) { +// Read implements the standard Read interface: +// 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 nil. +func (r *PipeReader) Read(data []byte) (n int, err os.Error) { r.lock.Lock(); defer r.lock.Unlock(); return r.p.Read(data); } -func (r *pipeRead) Close() os.Error { +// 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 { + r.lock.Lock(); + defer r.lock.Unlock(); + + return r.p.CloseReader(nil); +} + +// CloseWithError closes the reader; subsequent writes +// to the write half of the pipe will return the error rerr. +func (r *PipeReader) CloseWithError(rerr os.Error) os.Error { r.lock.Lock(); defer r.lock.Unlock(); - return r.p.CloseReader(); + return r.p.CloseReader(rerr); } -func (r *pipeRead) finish() { +func (r *PipeReader) finish() { r.Close(); } // Write half of pipe. -type pipeWrite struct { +type PipeWriter struct { lock sync.Mutex; p *pipe; } -func (w *pipeWrite) Write(data []byte) (n int, err os.Error) { +// Write implements the standard Write interface: +// 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) { w.lock.Lock(); defer w.lock.Unlock(); return w.p.Write(data); } -func (w *pipeWrite) Close() os.Error { +// Close closes the writer; subsequent reads from the +// read half of the pipe will return no bytes and a nil error. +func (w *PipeWriter) Close() os.Error { + w.lock.Lock(); + defer w.lock.Unlock(); + + return w.p.CloseWriter(nil); +} + +// CloseWithError closes the writer; subsequent reads from the +// read half of the pipe will return no bytes and the error werr. +func (w *PipeWriter) CloseWithError(werr os.Error) os.Error { w.lock.Lock(); defer w.lock.Unlock(); - return w.p.CloseWriter(); + return w.p.CloseWriter(werr); } -func (w *pipeWrite) finish() { +func (w *PipeWriter) finish() { w.Close(); } // Pipe creates a synchronous in-memory pipe. -// Used to connect code expecting an io.Reader +// It can be used to connect code expecting an io.Reader // with code expecting an io.Writer. -// -// Reads on one end are matched by writes on the other. -// Writes don't complete until all the data has been -// written or the read end is closed. Reads return -// any available data or block until the next write -// or the write end is closed. -func Pipe() (io.ReadCloser, io.WriteCloser) { +// Reads on one end are matched with writes on the other. +func Pipe() (*PipeReader, *PipeWriter) { p := new(pipe); p.cr = make(chan []byte, 1); p.cw = make(chan pipeReturn, 1); - r := new(pipeRead); + r := new(PipeReader); r.p = p; - w := new(pipeWrite); + w := new(PipeWriter); w.p = p; return r, w; } |
