return err
}
+var flateReaderPool sync.Pool
+
+func newFlateReader(r io.Reader) io.ReadCloser {
+ fr, ok := flateReaderPool.Get().(io.ReadCloser)
+ if ok {
+ fr.(flate.Resetter).Reset(r, nil)
+ } else {
+ fr = flate.NewReader(r)
+ }
+ return &pooledFlateReader{fr: fr}
+}
+
+type pooledFlateReader struct {
+ mu sync.Mutex // guards Close and Read
+ fr io.ReadCloser
+}
+
+func (r *pooledFlateReader) Read(p []byte) (n int, err error) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.fr == nil {
+ return 0, errors.New("Read after Close")
+ }
+ return r.fr.Read(p)
+}
+
+func (r *pooledFlateReader) Close() error {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ var err error
+ if r.fr != nil {
+ err = r.fr.Close()
+ flateReaderPool.Put(r.fr)
+ r.fr = nil
+ }
+ return err
+}
+
var (
mu sync.RWMutex // guards compressor and decompressor maps
decompressors = map[uint16]Decompressor{
Store: ioutil.NopCloser,
- Deflate: flate.NewReader,
+ Deflate: newFlateReader,
}
)