decred.org/dcrwallet/v3@v3.1.0/lru/cache.go (about) 1 // Copyright (c) 2018 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package lru 6 7 import ( 8 "container/list" 9 "sync" 10 ) 11 12 // Cache implements a least-recently-updated (LRU) cache with nearly O(1) 13 // lookups and inserts. Items are added to the cache up to a limit, at which 14 // point further additions will evict the least recently added item. The zero 15 // value is not valid and Caches must be created with NewCache. All Cache 16 // methods are concurrent safe. 17 type Cache struct { 18 mu sync.Mutex 19 m map[interface{}]*list.Element 20 list *list.List 21 limit int 22 } 23 24 // NewCache creates an initialized and empty LRU cache. 25 func NewCache(limit int) Cache { 26 return Cache{ 27 m: make(map[interface{}]*list.Element, limit), 28 list: list.New(), 29 limit: limit, 30 } 31 } 32 33 // Add adds an item to the LRU cache, removing the oldest item if the new item 34 // is not already a member, or marking item as the most recently added item if 35 // it is already present. 36 func (c *Cache) Add(item interface{}) { 37 defer c.mu.Unlock() 38 c.mu.Lock() 39 40 // Move this item to front of list if already present 41 elem, ok := c.m[item] 42 if ok { 43 c.list.MoveToFront(elem) 44 return 45 } 46 47 // If necessary, make room by popping an item off from the back 48 if len(c.m) > c.limit { 49 elem := c.list.Back() 50 if elem != nil { 51 v := c.list.Remove(elem) 52 delete(c.m, v) 53 } 54 } 55 56 // Add new item to the LRU 57 elem = c.list.PushFront(item) 58 c.m[item] = elem 59 } 60 61 // Contains checks whether v is a member of the LRU cache. 62 func (c *Cache) Contains(v interface{}) bool { 63 c.mu.Lock() 64 _, ok := c.m[v] 65 c.mu.Unlock() 66 return ok 67 }