github.com/glycerine/docker@v1.8.2/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 // Pool which returns bufio.Reader with a 32K buffer 22 BufioReader32KPool *BufioReaderPool 23 // Pool which returns bufio.Writer with a 32K buffer 24 BufioWriter32KPool *BufioWriterPool 25 ) 26 27 const buffer32K = 32 * 1024 28 29 type BufioReaderPool struct { 30 pool sync.Pool 31 } 32 33 func init() { 34 BufioReader32KPool = newBufioReaderPoolWithSize(buffer32K) 35 BufioWriter32KPool = newBufioWriterPoolWithSize(buffer32K) 36 } 37 38 // newBufioReaderPoolWithSize is unexported because new pools should be 39 // added here to be shared where required. 40 func newBufioReaderPoolWithSize(size int) *BufioReaderPool { 41 pool := sync.Pool{ 42 New: func() interface{} { return bufio.NewReaderSize(nil, size) }, 43 } 44 return &BufioReaderPool{pool: pool} 45 } 46 47 // Get returns a bufio.Reader which reads from r. The buffer size is that of the pool. 48 func (bufPool *BufioReaderPool) Get(r io.Reader) *bufio.Reader { 49 buf := bufPool.pool.Get().(*bufio.Reader) 50 buf.Reset(r) 51 return buf 52 } 53 54 // Put puts the bufio.Reader back into the pool. 55 func (bufPool *BufioReaderPool) Put(b *bufio.Reader) { 56 b.Reset(nil) 57 bufPool.pool.Put(b) 58 } 59 60 // Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy 61 func Copy(dst io.Writer, src io.Reader) (written int64, err error) { 62 buf := BufioReader32KPool.Get(src) 63 written, err = io.Copy(dst, buf) 64 BufioReader32KPool.Put(buf) 65 return 66 } 67 68 // NewReadCloserWrapper returns a wrapper which puts the bufio.Reader back 69 // into the pool and closes the reader if it's an io.ReadCloser. 70 func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Reader) io.ReadCloser { 71 return ioutils.NewReadCloserWrapper(r, func() error { 72 if readCloser, ok := r.(io.ReadCloser); ok { 73 readCloser.Close() 74 } 75 bufPool.Put(buf) 76 return nil 77 }) 78 } 79 80 type BufioWriterPool struct { 81 pool sync.Pool 82 } 83 84 // newBufioWriterPoolWithSize is unexported because new pools should be 85 // added here to be shared where required. 86 func newBufioWriterPoolWithSize(size int) *BufioWriterPool { 87 pool := sync.Pool{ 88 New: func() interface{} { return bufio.NewWriterSize(nil, size) }, 89 } 90 return &BufioWriterPool{pool: pool} 91 } 92 93 // Get returns a bufio.Writer which writes to w. The buffer size is that of the pool. 94 func (bufPool *BufioWriterPool) Get(w io.Writer) *bufio.Writer { 95 buf := bufPool.pool.Get().(*bufio.Writer) 96 buf.Reset(w) 97 return buf 98 } 99 100 // Put puts the bufio.Writer back into the pool. 101 func (bufPool *BufioWriterPool) Put(b *bufio.Writer) { 102 b.Reset(nil) 103 bufPool.pool.Put(b) 104 } 105 106 // NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back 107 // into the pool and closes the writer if it's an io.Writecloser. 108 func (bufPool *BufioWriterPool) NewWriteCloserWrapper(buf *bufio.Writer, w io.Writer) io.WriteCloser { 109 return ioutils.NewWriteCloserWrapper(w, func() error { 110 buf.Flush() 111 if writeCloser, ok := w.(io.WriteCloser); ok { 112 writeCloser.Close() 113 } 114 bufPool.Put(buf) 115 return nil 116 }) 117 }