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 }