/
syncPool.go
79 lines (74 loc) · 2.11 KB
/
syncPool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package bufpool
import (
"bytes"
"fmt"
"sync"
)
// SyncPool maintains a free-list of buffers.
type SyncPool struct {
pool sync.Pool
pc poolConfig
}
// NewSyncPool creates a new FreeList. The pool size, size of new buffers, and max size of buffers
// to keep when returned to the pool can all be customized. Note that the PoolSize method has no
// effect for free-lists created with NewSyncPool, because the Go runtime dynamically maintains the
// size of pools created using sync.Pool.
//
// package main
//
// import (
// "log"
//
// "github.com/karrick/bufpool"
// )
//
// func main() {
// bp, err := bufpool.NewSyncPool()
// if err != nil {
// log.Fatal(err)
// }
// for i := 0; i < 4*bufpool.DefaultPoolSize; i++ {
// go func() {
// for j := 0; j < 1000; j++ {
// bb := bp.Get()
// for k := 0; k < 3*bufpool.DefaultBufSize; k++ {
// bb.WriteByte(byte(k % 256))
// }
// bp.Put(bb)
// }
// }()
// }
// }
func NewSyncPool(setters ...Configurator) (FreeList, error) {
pc := &poolConfig{
poolSize: DefaultPoolSize,
bufSize: DefaultBufSize,
maxKeep: DefaultMaxKeep,
}
for _, setter := range setters {
if err := setter(pc); err != nil {
return nil, err
}
}
if pc.maxKeep < pc.bufSize {
return nil, fmt.Errorf("max buffer size must be greater or equal to default buffer size: %d, %d", pc.maxKeep, pc.bufSize)
}
bp := &SyncPool{pc: *pc}
bp.pool.New = func() interface{} {
return bytes.NewBuffer(make([]byte, 0, bp.pc.bufSize))
}
return bp, nil
}
// Get returns an initialized buffer from the free-list.
func (bp *SyncPool) Get() *bytes.Buffer {
return bp.pool.Get().(*bytes.Buffer)
}
// Put will return a used buffer back to the free-list. If the capacity of the used buffer grew
// beyond the max buffer size, it will be discarded and its memory returned to the runtime.
func (bp *SyncPool) Put(bb *bytes.Buffer) {
if bb.Cap() > bp.pc.maxKeep {
return // drop buffer on floor if too big
}
bb.Reset()
bp.pool.Put(bb)
}