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  }