github.com/MetalBlockchain/metalgo@v1.11.9/x/merkledb/bytes_pool.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package merkledb
     5  
     6  import "sync"
     7  
     8  type bytesPool struct {
     9  	slots     chan struct{}
    10  	bytesLock sync.Mutex
    11  	bytes     [][]byte
    12  }
    13  
    14  func newBytesPool(numSlots int) *bytesPool {
    15  	return &bytesPool{
    16  		slots: make(chan struct{}, numSlots),
    17  		bytes: make([][]byte, 0, numSlots),
    18  	}
    19  }
    20  
    21  func (p *bytesPool) Acquire() []byte {
    22  	p.slots <- struct{}{}
    23  	return p.pop()
    24  }
    25  
    26  func (p *bytesPool) TryAcquire() ([]byte, bool) {
    27  	select {
    28  	case p.slots <- struct{}{}:
    29  		return p.pop(), true
    30  	default:
    31  		return nil, false
    32  	}
    33  }
    34  
    35  func (p *bytesPool) pop() []byte {
    36  	p.bytesLock.Lock()
    37  	defer p.bytesLock.Unlock()
    38  
    39  	numBytes := len(p.bytes)
    40  	if numBytes == 0 {
    41  		return nil
    42  	}
    43  
    44  	b := p.bytes[numBytes-1]
    45  	p.bytes = p.bytes[:numBytes-1]
    46  	return b
    47  }
    48  
    49  func (p *bytesPool) Release(b []byte) {
    50  	// Before waking anyone waiting on a slot, return the bytes.
    51  	p.bytesLock.Lock()
    52  	p.bytes = append(p.bytes, b)
    53  	p.bytesLock.Unlock()
    54  
    55  	select {
    56  	case <-p.slots:
    57  	default:
    58  		panic("release of unacquired semaphore")
    59  	}
    60  }