github.com/kiali/kiali@v1.84.0/tracing/tempo/tempopb/pool/pool.go (about)

     1  // Forked with love from: https://github.com/prometheus/prometheus/tree/c954cd9d1d4e3530be2939d39d8633c38b70913f/util/pool
     2  // This package was forked to provide better protection against putting byte slices back into the pool that
     3  // did not originate from it.
     4  
     5  package pool
     6  
     7  import (
     8  	"sync"
     9  )
    10  
    11  // Pool is a bucketed pool for variably sized byte slices.
    12  type Pool struct {
    13  	buckets []sync.Pool
    14  	sizes   []int
    15  	// make is the function used to create an empty slice when none exist yet.
    16  	make func(int) []byte
    17  }
    18  
    19  // New returns a new Pool with size buckets for minSize to maxSize
    20  // increasing by the given factor.
    21  func New(minSize, maxSize int, factor float64, makeFunc func(int) []byte) *Pool {
    22  	if minSize < 1 {
    23  		panic("invalid minimum pool size")
    24  	}
    25  	if maxSize < 1 {
    26  		panic("invalid maximum pool size")
    27  	}
    28  	if factor < 1 {
    29  		panic("invalid factor")
    30  	}
    31  
    32  	var sizes []int
    33  
    34  	for s := minSize; s <= maxSize; s = int(float64(s) * factor) {
    35  		sizes = append(sizes, s)
    36  	}
    37  
    38  	p := &Pool{
    39  		buckets: make([]sync.Pool, len(sizes)),
    40  		sizes:   sizes,
    41  		make:    makeFunc,
    42  	}
    43  
    44  	return p
    45  }
    46  
    47  // Get returns a new byte slices that fits the given size.
    48  func (p *Pool) Get(sz int) []byte {
    49  	for i, bktSize := range p.sizes {
    50  		if sz > bktSize {
    51  			continue
    52  		}
    53  		b := p.buckets[i].Get()
    54  		if b == nil {
    55  			b = p.make(bktSize)
    56  		}
    57  		return b.([]byte)
    58  	}
    59  	return p.make(sz)
    60  }
    61  
    62  // Put adds a slice to the right bucket in the pool. This method has been adjusted from its initial
    63  // implementation to ignore byte slices that dont have the correct size
    64  func (p *Pool) Put(s []byte) {
    65  	c := cap(s)
    66  	for i, size := range p.sizes {
    67  		if c == size {
    68  			p.buckets[i].Put(s) // nolint: staticcheck
    69  		}
    70  		if c < size {
    71  			return
    72  		}
    73  	}
    74  }