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