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 }