github.com/aaabigfish/gopkg@v1.1.0/cache/lrucache/lrucache.go (about)

     1  package lrucache
     2  
     3  // Element - node to store cache item
     4  type Element struct {
     5  	prev, next *Element
     6  	Key        interface{}
     7  	Value      interface{}
     8  }
     9  
    10  // Next - fetch older element
    11  func (e *Element) Next() *Element {
    12  	return e.next
    13  }
    14  
    15  // Prev - fetch newer element
    16  func (e *Element) Prev() *Element {
    17  	return e.prev
    18  }
    19  
    20  // LRUCache - a data structure that is efficient to insert/fetch/delete cache items [both O(1) time complexity]
    21  type LRUCache struct {
    22  	cache    map[interface{}]*Element
    23  	head     *Element
    24  	tail     *Element
    25  	capacity int
    26  }
    27  
    28  // New - create a new lru cache object
    29  func New(capacity int) *LRUCache {
    30  	return &LRUCache{make(map[interface{}]*Element), nil, nil, capacity}
    31  }
    32  
    33  // Put - put a cache item into lru cache
    34  func (lc *LRUCache) Put(key interface{}, value interface{}) {
    35  	if e, ok := lc.cache[key]; ok {
    36  		e.Value = value
    37  		lc.refresh(e)
    38  		return
    39  	}
    40  
    41  	if lc.capacity == 0 {
    42  		return
    43  	} else if len(lc.cache) >= lc.capacity {
    44  		// evict the oldest item
    45  		delete(lc.cache, lc.tail.Key)
    46  		lc.remove(lc.tail)
    47  	}
    48  
    49  	e := &Element{nil, lc.head, key, value}
    50  	lc.cache[key] = e
    51  	if len(lc.cache) != 1 {
    52  		lc.head.prev = e
    53  	} else {
    54  		lc.tail = e
    55  	}
    56  	lc.head = e
    57  }
    58  
    59  // Get - get value of key from lru cache with result
    60  func (lc *LRUCache) Get(key interface{}) (interface{}, bool) {
    61  	if e, ok := lc.cache[key]; ok {
    62  		lc.refresh(e)
    63  		return e.Value, ok
    64  	}
    65  	return nil, false
    66  }
    67  
    68  // Delete - delete item by key from lru cache
    69  func (lc *LRUCache) Delete(key interface{}) {
    70  	if e, ok := lc.cache[key]; ok {
    71  		delete(lc.cache, key)
    72  		lc.remove(e)
    73  	}
    74  }
    75  
    76  // Range - calls f sequentially for each key and value present in the lru cache
    77  func (lc *LRUCache) Range(f func(key, value interface{}) bool) {
    78  	for i := lc.head; i != nil; i = i.Next() {
    79  		if !f(i.Key, i.Value) {
    80  			break
    81  		}
    82  	}
    83  }
    84  
    85  // Update - inplace update
    86  func (lc *LRUCache) Update(key interface{}, f func(value *interface{})) {
    87  	if e, ok := lc.cache[key]; ok {
    88  		f(&e.Value)
    89  		lc.refresh(e)
    90  	}
    91  }
    92  
    93  // Front - get front element of lru cache
    94  func (lc *LRUCache) Front() *Element {
    95  	return lc.head
    96  }
    97  
    98  // Back - get back element of lru cache
    99  func (lc *LRUCache) Back() *Element {
   100  	return lc.tail
   101  }
   102  
   103  // Len - length of lru cache
   104  func (lc *LRUCache) Len() int {
   105  	return len(lc.cache)
   106  }
   107  
   108  // Capacity - capacity of lru cache
   109  func (lc *LRUCache) Capacity() int {
   110  	return lc.capacity
   111  }
   112  
   113  func (lc *LRUCache) refresh(e *Element) {
   114  	if e.prev != nil {
   115  		e.prev.next = e.next
   116  		if e.next == nil {
   117  			lc.tail = e.prev
   118  		} else {
   119  			e.next.prev = e.prev
   120  		}
   121  		e.prev = nil
   122  		e.next = lc.head
   123  		lc.head.prev = e
   124  		lc.head = e
   125  	}
   126  }
   127  
   128  func (lc *LRUCache) remove(e *Element) {
   129  	if e.prev == nil {
   130  		lc.head = e.next
   131  	} else {
   132  		e.prev.next = e.next
   133  	}
   134  	if e.next == nil {
   135  		lc.tail = e.prev
   136  	} else {
   137  		e.next.prev = e.prev
   138  	}
   139  }