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

     1  // (c) 2021, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package core
     5  
     6  import (
     7  	"sync"
     8  )
     9  
    10  var (
    11  	_ FIFOCache[int, int] = (*BufferFIFOCache[int, int])(nil)
    12  	_ FIFOCache[int, int] = (*NoOpFIFOCache[int, int])(nil)
    13  )
    14  
    15  // FIFOCache evicts the oldest element added to it after [limit] items are
    16  // added.
    17  type FIFOCache[K comparable, V any] interface {
    18  	Put(K, V)
    19  	Get(K) (V, bool)
    20  }
    21  
    22  // NewFIFOCache creates a new First-In-First-Out cache of size [limit].
    23  //
    24  // If a [limit] of 0 is passed as an argument, a no-op cache is returned that
    25  // does nothing.
    26  func NewFIFOCache[K comparable, V any](limit int) FIFOCache[K, V] {
    27  	if limit <= 0 {
    28  		return &NoOpFIFOCache[K, V]{}
    29  	}
    30  
    31  	c := &BufferFIFOCache[K, V]{
    32  		m: make(map[K]V, limit),
    33  	}
    34  	c.buffer = NewBoundedBuffer(limit, c.remove)
    35  	return c
    36  }
    37  
    38  type BufferFIFOCache[K comparable, V any] struct {
    39  	l sync.RWMutex
    40  
    41  	buffer *BoundedBuffer[K]
    42  	m      map[K]V
    43  }
    44  
    45  func (f *BufferFIFOCache[K, V]) Put(key K, val V) {
    46  	f.l.Lock()
    47  	defer f.l.Unlock()
    48  
    49  	f.buffer.Insert(key) // Insert will remove the oldest [K] if we are at the [limit]
    50  	f.m[key] = val
    51  }
    52  
    53  func (f *BufferFIFOCache[K, V]) Get(key K) (V, bool) {
    54  	f.l.RLock()
    55  	defer f.l.RUnlock()
    56  
    57  	v, ok := f.m[key]
    58  	return v, ok
    59  }
    60  
    61  // remove is used as the callback in [BoundedBuffer]. It is assumed that the
    62  // [WriteLock] is held when this is accessed.
    63  func (f *BufferFIFOCache[K, V]) remove(key K) {
    64  	delete(f.m, key)
    65  }
    66  
    67  type NoOpFIFOCache[K comparable, V any] struct{}
    68  
    69  func (f *NoOpFIFOCache[K, V]) Put(_ K, _ V) {}
    70  func (f *NoOpFIFOCache[K, V]) Get(_ K) (V, bool) {
    71  	return *new(V), false
    72  }