github.com/bhojpur/cache@v0.0.4/pkg/pools/pools.go (about) 1 package pools 2 3 // Copyright (c) 2018 Bhojpur Consulting Private Limited, India. All rights reserved. 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 // THE SOFTWARE. 22 23 // Package pools provides a collection of pools which provide various data 24 // types with buffers. These can be used to lower the number of memory 25 // allocations and reuse buffers. 26 // 27 // New pools should be added to this package to allow them to be shared across 28 // packages. 29 // 30 // Utility functions which operate on pools should be added to this package to 31 // allow them to be reused. 32 33 import ( 34 "bufio" 35 "io" 36 "sync" 37 38 "github.com/bhojpur/cache/pkg/ioutils" 39 ) 40 41 const buffer32K = 32 * 1024 42 43 var ( 44 // BufioReader32KPool is a pool which returns bufio.Reader with a 32K buffer. 45 BufioReader32KPool = newBufioReaderPoolWithSize(buffer32K) 46 // BufioWriter32KPool is a pool which returns bufio.Writer with a 32K buffer. 47 BufioWriter32KPool = newBufioWriterPoolWithSize(buffer32K) 48 buffer32KPool = newBufferPoolWithSize(buffer32K) 49 ) 50 51 // BufioReaderPool is a bufio reader that uses sync.Pool. 52 type BufioReaderPool struct { 53 pool sync.Pool 54 } 55 56 // newBufioReaderPoolWithSize is unexported because new pools should be 57 // added here to be shared where required. 58 func newBufioReaderPoolWithSize(size int) *BufioReaderPool { 59 return &BufioReaderPool{ 60 pool: sync.Pool{ 61 New: func() interface{} { return bufio.NewReaderSize(nil, size) }, 62 }, 63 } 64 } 65 66 // Get returns a bufio.Reader which reads from r. The buffer size is that of the pool. 67 func (bufPool *BufioReaderPool) Get(r io.Reader) *bufio.Reader { 68 buf := bufPool.pool.Get().(*bufio.Reader) 69 buf.Reset(r) 70 return buf 71 } 72 73 // Put puts the bufio.Reader back into the pool. 74 func (bufPool *BufioReaderPool) Put(b *bufio.Reader) { 75 b.Reset(nil) 76 bufPool.pool.Put(b) 77 } 78 79 type bufferPool struct { 80 pool sync.Pool 81 } 82 83 func newBufferPoolWithSize(size int) *bufferPool { 84 return &bufferPool{ 85 pool: sync.Pool{ 86 New: func() interface{} { s := make([]byte, size); return &s }, 87 }, 88 } 89 } 90 91 func (bp *bufferPool) Get() *[]byte { 92 return bp.pool.Get().(*[]byte) 93 } 94 95 func (bp *bufferPool) Put(b *[]byte) { 96 bp.pool.Put(b) 97 } 98 99 // Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy. 100 func Copy(dst io.Writer, src io.Reader) (written int64, err error) { 101 buf := buffer32KPool.Get() 102 written, err = io.CopyBuffer(dst, src, *buf) 103 buffer32KPool.Put(buf) 104 return 105 } 106 107 // NewReadCloserWrapper returns a wrapper which puts the bufio.Reader back 108 // into the pool and closes the reader if it's an io.ReadCloser. 109 func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Reader) io.ReadCloser { 110 return ioutils.NewReadCloserWrapper(r, func() error { 111 if readCloser, ok := r.(io.ReadCloser); ok { 112 readCloser.Close() 113 } 114 bufPool.Put(buf) 115 return nil 116 }) 117 } 118 119 // BufioWriterPool is a bufio writer that uses sync.Pool. 120 type BufioWriterPool struct { 121 pool sync.Pool 122 } 123 124 // newBufioWriterPoolWithSize is unexported because new pools should be 125 // added here to be shared where required. 126 func newBufioWriterPoolWithSize(size int) *BufioWriterPool { 127 return &BufioWriterPool{ 128 pool: sync.Pool{ 129 New: func() interface{} { return bufio.NewWriterSize(nil, size) }, 130 }, 131 } 132 } 133 134 // Get returns a bufio.Writer which writes to w. The buffer size is that of the pool. 135 func (bufPool *BufioWriterPool) Get(w io.Writer) *bufio.Writer { 136 buf := bufPool.pool.Get().(*bufio.Writer) 137 buf.Reset(w) 138 return buf 139 } 140 141 // Put puts the bufio.Writer back into the pool. 142 func (bufPool *BufioWriterPool) Put(b *bufio.Writer) { 143 b.Reset(nil) 144 bufPool.pool.Put(b) 145 } 146 147 // NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back 148 // into the pool and closes the writer if it's an io.Writecloser. 149 func (bufPool *BufioWriterPool) NewWriteCloserWrapper(buf *bufio.Writer, w io.Writer) io.WriteCloser { 150 return ioutils.NewWriteCloserWrapper(w, func() error { 151 buf.Flush() 152 if writeCloser, ok := w.(io.WriteCloser); ok { 153 writeCloser.Close() 154 } 155 bufPool.Put(buf) 156 return nil 157 }) 158 }