123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- package cache
- import (
- "container/list"
- "sync"
- )
- // Cache is an LRU cache. It is safe for concurrent access.
- type Cache struct {
- // MaxEntries is the maximum number of cache entries before
- // an item is evicted. Zero means no limit.
- MaxEntries int
- //Execute this callback function when an element is culled
- OnEvicted func(key Key, value interface{})
- ll *list.List //list
- cache sync.Map
- }
- // A Key may be any value that is comparable. See http://golang.org/ref/spec#Comparison_operators
- type Key interface{}
- type entry struct {
- key Key
- value interface{}
- }
- // New creates a new Cache.
- // If maxEntries is 0, the cache has no length limit.
- // that eviction is done by the caller.
- func New(maxEntries int) *Cache {
- return &Cache{
- MaxEntries: maxEntries,
- ll: list.New(),
- //cache: make(map[interface{}]*list.Element),
- }
- }
- // If the key value already exists, move the key to the front
- func (c *Cache) Add(key Key, value interface{}) {
- if ee, ok := c.cache.Load(key); ok {
- c.ll.MoveToFront(ee.(*list.Element)) // move to the front
- ee.(*list.Element).Value.(*entry).value = value
- return
- }
- ele := c.ll.PushFront(&entry{key, value})
- c.cache.Store(key, ele)
- if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries { // Remove the oldest element if the limit is exceeded
- c.RemoveOldest()
- }
- }
- // Get looks up a key's value from the cache.
- func (c *Cache) Get(key Key) (value interface{}, ok bool) {
- if ele, hit := c.cache.Load(key); hit {
- c.ll.MoveToFront(ele.(*list.Element))
- return ele.(*list.Element).Value.(*entry).value, true
- }
- return
- }
- // Remove removes the provided key from the cache.
- func (c *Cache) Remove(key Key) {
- if ele, hit := c.cache.Load(key); hit {
- c.removeElement(ele.(*list.Element))
- }
- }
- // RemoveOldest removes the oldest item from the cache.
- func (c *Cache) RemoveOldest() {
- ele := c.ll.Back()
- if ele != nil {
- c.removeElement(ele)
- }
- }
- func (c *Cache) removeElement(e *list.Element) {
- c.ll.Remove(e)
- kv := e.Value.(*entry)
- c.cache.Delete(kv.key)
- if c.OnEvicted != nil {
- c.OnEvicted(kv.key, kv.value)
- }
- }
- // Len returns the number of items in the cache.
- func (c *Cache) Len() int {
- return c.ll.Len()
- }
- // Clear purges all stored items from the cache.
- func (c *Cache) Clear() {
- if c.OnEvicted != nil {
- c.cache.Range(func(key, value interface{}) bool {
- kv := value.(*list.Element).Value.(*entry)
- c.OnEvicted(kv.key, kv.value)
- return true
- })
- }
- c.ll = nil
- }
|