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 }