2018-03-30 20:43:18 +00:00
|
|
|
package archiver
|
|
|
|
|
|
|
|
// Buffer is a reusable buffer. After the buffer has been used, Release should
|
|
|
|
// be called so the underlying slice is put back into the pool.
|
|
|
|
type Buffer struct {
|
|
|
|
Data []byte
|
2022-05-29 15:07:37 +00:00
|
|
|
pool *BufferPool
|
2018-03-30 20:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Release puts the buffer back into the pool it came from.
|
2018-04-29 13:34:41 +00:00
|
|
|
func (b *Buffer) Release() {
|
2022-05-29 15:07:37 +00:00
|
|
|
pool := b.pool
|
|
|
|
if pool == nil || cap(b.Data) > pool.defaultSize {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case pool.ch <- b:
|
|
|
|
default:
|
2018-03-30 20:43:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// BufferPool implements a limited set of reusable buffers.
|
|
|
|
type BufferPool struct {
|
2018-04-29 13:34:41 +00:00
|
|
|
ch chan *Buffer
|
2018-03-30 20:43:18 +00:00
|
|
|
defaultSize int
|
|
|
|
}
|
|
|
|
|
2022-05-29 15:07:37 +00:00
|
|
|
// NewBufferPool initializes a new buffer pool. The pool stores at most max
|
|
|
|
// items. New buffers are created with defaultSize. Buffers that have grown
|
|
|
|
// larger are not put back.
|
|
|
|
func NewBufferPool(max int, defaultSize int) *BufferPool {
|
2018-03-30 20:43:18 +00:00
|
|
|
b := &BufferPool{
|
2018-04-29 13:34:41 +00:00
|
|
|
ch: make(chan *Buffer, max),
|
2018-03-30 20:43:18 +00:00
|
|
|
defaultSize: defaultSize,
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get returns a new buffer, either from the pool or newly allocated.
|
2018-04-29 13:34:41 +00:00
|
|
|
func (pool *BufferPool) Get() *Buffer {
|
2018-03-30 20:43:18 +00:00
|
|
|
select {
|
|
|
|
case buf := <-pool.ch:
|
2018-04-29 13:34:41 +00:00
|
|
|
return buf
|
2018-03-30 20:43:18 +00:00
|
|
|
default:
|
2018-04-29 13:34:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
b := &Buffer{
|
|
|
|
Data: make([]byte, pool.defaultSize),
|
2022-05-29 15:07:37 +00:00
|
|
|
pool: pool,
|
2018-03-30 20:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return b
|
|
|
|
}
|