github.com/akerouanton/docker@v1.11.0-rc3/pkg/pools/pools.go (about)

     1  // Package pools provides a collection of pools which provide various
     2  // data types with buffers. These can be used to lower the number of
     3  // memory allocations and reuse buffers.
     4  //
     5  // New pools should be added to this package to allow them to be
     6  // shared across packages.
     7  //
     8  // Utility functions which operate on pools should be added to this
     9  // package to allow them to be reused.
    10  package pools
    11  
    12  import (
    13  	"bufio"
    14  	"io"
    15  	"sync"
    16  
    17  	"github.com/docker/docker/pkg/ioutils"
    18  )
    19  
    20  var (
    21  	// BufioReader32KPool is a pool which returns bufio.Reader with a 32K buffer.
    22  	BufioReader32KPool *BufioReaderPool
    23  	// BufioWriter32KPool is a pool which returns bufio.Writer with a 32K buffer.
    24  	BufioWriter32KPool *BufioWriterPool
    25  )
    26  
    27  const buffer32K = 32 * 1024
    28  
    29  // BufioReaderPool is a bufio reader that uses sync.Pool.
    30  type BufioReaderPool struct {
    31  	pool sync.Pool
    32  }
    33  
    34  func init() {
    35  	BufioReader32KPool = newBufioReaderPoolWithSize(buffer32K)
    36  	BufioWriter32KPool = newBufioWriterPoolWithSize(buffer32K)
    37  }
    38  
    39  // newBufioReaderPoolWithSize is unexported because new pools should be
    40  // added here to be shared where required.
    41  func newBufioReaderPoolWithSize(size int) *BufioReaderPool {
    42  	pool := sync.Pool{
    43  		New: func() interface{} { return bufio.NewReaderSize(nil, size) },
    44  	}
    45  	return &BufioReaderPool{pool: pool}
    46  }
    47  
    48  // Get returns a bufio.Reader which reads from r. The buffer size is that of the pool.
    49  func (bufPool *BufioReaderPool) Get(r io.Reader) *bufio.Reader {
    50  	buf := bufPool.pool.Get().(*bufio.Reader)
    51  	buf.Reset(r)
    52  	return buf
    53  }
    54  
    55  // Put puts the bufio.Reader back into the pool.
    56  func (bufPool *BufioReaderPool) Put(b *bufio.Reader) {
    57  	b.Reset(nil)
    58  	bufPool.pool.Put(b)
    59  }
    60  
    61  // Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy.
    62  func Copy(dst io.Writer, src io.Reader) (written int64, err error) {
    63  	buf := BufioReader32KPool.Get(src)
    64  	written, err = io.Copy(dst, buf)
    65  	BufioReader32KPool.Put(buf)
    66  	return
    67  }
    68  
    69  // NewReadCloserWrapper returns a wrapper which puts the bufio.Reader back
    70  // into the pool and closes the reader if it's an io.ReadCloser.
    71  func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Reader) io.ReadCloser {
    72  	return ioutils.NewReadCloserWrapper(r, func() error {
    73  		if readCloser, ok := r.(io.ReadCloser); ok {
    74  			readCloser.Close()
    75  		}
    76  		bufPool.Put(buf)
    77  		return nil
    78  	})
    79  }
    80  
    81  // BufioWriterPool is a bufio writer that uses sync.Pool.
    82  type BufioWriterPool struct {
    83  	pool sync.Pool
    84  }
    85  
    86  // newBufioWriterPoolWithSize is unexported because new pools should be
    87  // added here to be shared where required.
    88  func newBufioWriterPoolWithSize(size int) *BufioWriterPool {
    89  	pool := sync.Pool{
    90  		New: func() interface{} { return bufio.NewWriterSize(nil, size) },
    91  	}
    92  	return &BufioWriterPool{pool: pool}
    93  }
    94  
    95  // Get returns a bufio.Writer which writes to w. The buffer size is that of the pool.
    96  func (bufPool *BufioWriterPool) Get(w io.Writer) *bufio.Writer {
    97  	buf := bufPool.pool.Get().(*bufio.Writer)
    98  	buf.Reset(w)
    99  	return buf
   100  }
   101  
   102  // Put puts the bufio.Writer back into the pool.
   103  func (bufPool *BufioWriterPool) Put(b *bufio.Writer) {
   104  	b.Reset(nil)
   105  	bufPool.pool.Put(b)
   106  }
   107  
   108  // NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back
   109  // into the pool and closes the writer if it's an io.Writecloser.
   110  func (bufPool *BufioWriterPool) NewWriteCloserWrapper(buf *bufio.Writer, w io.Writer) io.WriteCloser {
   111  	return ioutils.NewWriteCloserWrapper(w, func() error {
   112  		buf.Flush()
   113  		if writeCloser, ok := w.(io.WriteCloser); ok {
   114  			writeCloser.Close()
   115  		}
   116  		bufPool.Put(buf)
   117  		return nil
   118  	})
   119  }