github.com/coreos/mantle@v0.13.0/lang/bufpipe/pipe.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  // Licensed under the same terms as Go itself:
     5  // https://github.com/golang/go/blob/master/LICENSE
     6  
     7  // Pipe adapter to connect code expecting an io.Reader
     8  // with code expecting an io.Writer.
     9  
    10  package bufpipe
    11  
    12  import (
    13  	"bytes"
    14  	"io"
    15  	"sync"
    16  )
    17  
    18  // A pipe is the shared pipe structure underlying PipeReader and PipeWriter.
    19  type pipe struct {
    20  	rl    sync.Mutex // gates readers one at a time
    21  	wl    sync.Mutex // gates writers one at a time
    22  	l     sync.Mutex // protects remaining fields
    23  	buf   pipeBuffer // data buffer
    24  	rwait sync.Cond  // waiting reader
    25  	wwait sync.Cond  // waiting writer
    26  	rerr  error      // if reader closed, error to give writes
    27  	werr  error      // if writer closed, error to give reads
    28  }
    29  
    30  type pipeBuffer interface {
    31  	Len() int
    32  	io.Writer
    33  	io.Reader
    34  }
    35  
    36  func newPipe(buf pipeBuffer) *pipe {
    37  	p := &pipe{buf: buf}
    38  	p.rwait.L = &p.l
    39  	p.wwait.L = &p.l
    40  	return p
    41  }
    42  
    43  func (p *pipe) read(b []byte) (n int, err error) {
    44  	// One reader at a time.
    45  	p.rl.Lock()
    46  	defer p.rl.Unlock()
    47  
    48  	p.l.Lock()
    49  	defer p.l.Unlock()
    50  	for {
    51  		if p.rerr != nil {
    52  			return 0, io.ErrClosedPipe
    53  		}
    54  		if p.buf.Len() > 0 {
    55  			break
    56  		}
    57  		if p.werr != nil {
    58  			return 0, p.werr
    59  		}
    60  		p.rwait.Wait()
    61  	}
    62  	n, err = p.buf.Read(b)
    63  	p.wwait.Signal()
    64  	return
    65  }
    66  
    67  var zero [0]byte
    68  
    69  func (p *pipe) write(b []byte) (n int, err error) {
    70  	// pipe uses nil to mean not available
    71  	if b == nil {
    72  		b = zero[:]
    73  	}
    74  
    75  	// One writer at a time.
    76  	p.wl.Lock()
    77  	defer p.wl.Unlock()
    78  
    79  	p.l.Lock()
    80  	defer p.l.Unlock()
    81  	for {
    82  		if p.werr != nil {
    83  			err = io.ErrClosedPipe
    84  			break
    85  		}
    86  		if p.rerr != nil {
    87  			err = p.rerr
    88  			break
    89  		}
    90  		nn, err := p.buf.Write(b[n:])
    91  		p.rwait.Signal()
    92  		n += nn
    93  		if err != errWriteFull {
    94  			break
    95  		}
    96  		p.wwait.Wait()
    97  	}
    98  	return
    99  }
   100  
   101  func (p *pipe) rclose(err error) {
   102  	if err == nil {
   103  		err = io.ErrClosedPipe
   104  	}
   105  	p.l.Lock()
   106  	defer p.l.Unlock()
   107  	p.rerr = err
   108  	p.rwait.Signal()
   109  	p.wwait.Signal()
   110  }
   111  
   112  func (p *pipe) wclose(err error) {
   113  	if err == nil {
   114  		err = io.EOF
   115  	}
   116  	p.l.Lock()
   117  	defer p.l.Unlock()
   118  	p.werr = err
   119  	p.rwait.Signal()
   120  	p.wwait.Signal()
   121  }
   122  
   123  // A PipeReader is the read half of a pipe.
   124  type PipeReader struct {
   125  	p *pipe
   126  }
   127  
   128  // Read implements the standard Read interface:
   129  // it reads data from the pipe, blocking until a writer
   130  // arrives or the write end is closed.
   131  // Closing the write end does not prevent reading buffered data.
   132  // If the write end is closed with an error, that error is
   133  // returned as err; otherwise err is io.EOF.
   134  func (r *PipeReader) Read(data []byte) (n int, err error) {
   135  	return r.p.read(data)
   136  }
   137  
   138  // Close closes the reader; subsequent writes to the
   139  // write half of the pipe will return the error io.ErrClosedPipe.
   140  func (r *PipeReader) Close() error {
   141  	return r.CloseWithError(nil)
   142  }
   143  
   144  // CloseWithError closes the reader; subsequent writes
   145  // to the write half of the pipe will return the error err.
   146  func (r *PipeReader) CloseWithError(err error) error {
   147  	r.p.rclose(err)
   148  	return nil
   149  }
   150  
   151  // A PipeWriter is the write half of a pipe.
   152  type PipeWriter struct {
   153  	p *pipe
   154  }
   155  
   156  // Write implements the standard Write interface:
   157  // it writes data to the pipe, returning once the data is
   158  // buffered or the read end is closed.
   159  // When using a FixedPipe, Write may block until one
   160  // or more readers have consumed some of the data.
   161  // If the read end is closed with an error, that err is
   162  // returned as err; otherwise err is io.ErrClosedPipe.
   163  func (w *PipeWriter) Write(data []byte) (n int, err error) {
   164  	return w.p.write(data)
   165  }
   166  
   167  // Close closes the writer.
   168  // Buffered data may still be read.
   169  // Once the buffer is empty subsequent reads from the
   170  // read half of the pipe will return no bytes and io.EOF.
   171  func (w *PipeWriter) Close() error {
   172  	return w.CloseWithError(nil)
   173  }
   174  
   175  // CloseWithError closes the writer.
   176  // Buffered data may still be read.
   177  // Once the buffer is empty subsequent reads from the
   178  // read half of the pipe will return no bytes and the error err,
   179  // or io.EOF if err is nil.
   180  //
   181  // CloseWithError always returns nil.
   182  func (w *PipeWriter) CloseWithError(err error) error {
   183  	w.p.wclose(err)
   184  	return nil
   185  }
   186  
   187  // Pipe creates a synchronous in-memory pipe with an unlimited buffer.
   188  // If the input size is unknown a FixedPipe may be preferable.
   189  //
   190  // Reads will block until data is written.
   191  // Writes will never block.
   192  //
   193  // It is safe to call Read and Write in parallel with each other or with Close.
   194  // Parallel calls to Read and parallel calls to Write are also safe:
   195  // the individual calls will be gated sequentially.
   196  func Pipe() (*PipeReader, *PipeWriter) {
   197  	p := newPipe(&bytes.Buffer{})
   198  	r := &PipeReader{p}
   199  	w := &PipeWriter{p}
   200  	return r, w
   201  }
   202  
   203  const minBufferSize = 16
   204  
   205  // FixedPipe creates a synchronous in-memory pipe with a
   206  // fixed-size buffer that has at least the specified size.
   207  // It can be used to mimic a kernel provided fifo or socket
   208  // which have an internal buffer and blocking I/O.
   209  //
   210  // Reads will block until data is written.
   211  // Writes will block when the internal buffer is filled.
   212  //
   213  // It is safe to call Read and Write in parallel with each other or with Close.
   214  // Parallel calls to Read and parallel calls to Write are also safe:
   215  // the individual calls will be gated sequentially.
   216  func FixedPipe(size int) (*PipeReader, *PipeWriter) {
   217  	if size < minBufferSize {
   218  		size = minBufferSize
   219  	}
   220  	p := newPipe(&fixedBuffer{buf: make([]byte, size)})
   221  	r := &PipeReader{p}
   222  	w := &PipeWriter{p}
   223  	return r, w
   224  }