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 }