github.com/MetalBlockchain/subnet-evm@v0.4.9/core/bounded_buffer.go (about)

     1  // (c) 2022, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package core
     5  
     6  // BoundedBuffer keeps [size] entries of type [K] in a buffer and calls
     7  // [callback] on any item that is overwritten. This is typically used for
     8  // dereferencing old roots during block processing.
     9  //
    10  // BoundedBuffer is not thread-safe and requires the caller synchronize usage.
    11  type BoundedBuffer[K any] struct {
    12  	lastPos  int
    13  	size     int
    14  	callback func(K)
    15  	buffer   []K
    16  
    17  	cycled bool
    18  }
    19  
    20  // NewBoundedBuffer creates a new [BoundedBuffer].
    21  func NewBoundedBuffer[K any](size int, callback func(K)) *BoundedBuffer[K] {
    22  	return &BoundedBuffer[K]{
    23  		lastPos:  -1,
    24  		size:     size,
    25  		callback: callback,
    26  		buffer:   make([]K, size),
    27  	}
    28  }
    29  
    30  // Insert adds a new value to the buffer. If the buffer is full, the
    31  // oldest value will be overwritten and [callback] will be invoked.
    32  func (b *BoundedBuffer[K]) Insert(h K) {
    33  	nextPos := b.lastPos + 1 // the first item added to the buffer will be at position 0
    34  	if nextPos == b.size {
    35  		nextPos = 0
    36  		// Set [cycled] since we are back to the 0th element
    37  		b.cycled = true
    38  	}
    39  	if b.cycled {
    40  		// We ensure we have cycled through the buffer once before invoking the
    41  		// [callback] to ensure we don't call it with unset values.
    42  		b.callback(b.buffer[nextPos])
    43  	}
    44  	b.buffer[nextPos] = h
    45  	b.lastPos = nextPos
    46  }
    47  
    48  // Last retrieves the last item added to the buffer.
    49  //
    50  // If no items have been added to the buffer, Last returns the default value of
    51  // [K] and [false].
    52  func (b *BoundedBuffer[K]) Last() (K, bool) {
    53  	if b.lastPos == -1 {
    54  		return *new(K), false
    55  	}
    56  	return b.buffer[b.lastPos], true
    57  }