123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- // Copyright (C) 2016 The Protocol Authors.
- package protocol
- import "sync"
- // Global pool to get buffers from. Requires Blocksizes to be initialised,
- // therefore it is initialized in the same init() as BlockSizes
- var BufferPool bufferPool
- type bufferPool struct {
- pools []sync.Pool
- }
- func newBufferPool() bufferPool {
- return bufferPool{make([]sync.Pool, len(BlockSizes))}
- }
- func (p *bufferPool) Get(size int) []byte {
- // Too big, isn't pooled
- if size > MaxBlockSize {
- return make([]byte, size)
- }
- var i int
- for i = range BlockSizes {
- if size <= BlockSizes[i] {
- break
- }
- }
- var bs []byte
- // Try the fitting and all bigger pools
- for j := i; j < len(BlockSizes); j++ {
- if intf := p.pools[j].Get(); intf != nil {
- bs = *intf.(*[]byte)
- return bs[:size]
- }
- }
- // All pools are empty, must allocate.
- return make([]byte, BlockSizes[i])[:size]
- }
- // Put makes the given byte slice availabe again in the global pool
- func (p *bufferPool) Put(bs []byte) {
- c := cap(bs)
- // Don't buffer huge byte slices
- if c > 2*MaxBlockSize {
- return
- }
- for i := range BlockSizes {
- if c >= BlockSizes[i] {
- p.pools[i].Put(&bs)
- return
- }
- }
- }
- // Upgrade grows the buffer to the requested size, while attempting to reuse
- // it if possible.
- func (p *bufferPool) Upgrade(bs []byte, size int) []byte {
- if cap(bs) >= size {
- // Reslicing is enough, lets go!
- return bs[:size]
- }
- // It was too small. But it pack into the pool and try to get another
- // buffer.
- p.Put(bs)
- return p.Get(size)
- }
|