github.com/joeygibson/docker@v1.5.0/pkg/pools/pools.go (about)

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