package cache import ( "container/list" "sync" "github.com/nspcc-dev/neo-go/pkg/util" ) // HashCache is a payload cache which is used to store // last consensus payloads. type HashCache struct { *sync.RWMutex maxCap int elems map[util.Uint256]*list.Element queue *list.List } // Hashable is a type of items which can be stored in the HashCache. type Hashable interface { Hash() util.Uint256 } // NewFIFOCache returns new FIFO cache with the specified capacity. func NewFIFOCache(capacity int) *HashCache { return &HashCache{ RWMutex: new(sync.RWMutex), maxCap: capacity, elems: make(map[util.Uint256]*list.Element), queue: list.New(), } } // Add adds payload into a cache if it doesn't already exist. func (c *HashCache) Add(p Hashable) { c.Lock() defer c.Unlock() h := p.Hash() if c.elems[h] != nil { return } if c.queue.Len() >= c.maxCap { first := c.queue.Front() c.queue.Remove(first) delete(c.elems, first.Value.(Hashable).Hash()) } e := c.queue.PushBack(p) c.elems[h] = e } // Has checks if an item is already in cache. func (c *HashCache) Has(h util.Uint256) bool { c.RLock() defer c.RUnlock() return c.elems[h] != nil } // Get returns payload with the specified hash from cache. func (c *HashCache) Get(h util.Uint256) Hashable { c.RLock() defer c.RUnlock() e, ok := c.elems[h] if !ok { return Hashable(nil) } return e.Value.(Hashable) }