]>
Commit | Line | Data |
---|---|---|
9b12e4fe JC |
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/fsouza/go-dockerclient/external/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 | } |