blob: 6a5ce6faccc49ede4046e4fc46227d550012f9f9 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package cache provides methods for creating and using a cache.
package cache
import "container/list"
// A Key may be any value that is comparable.
type Key interface{}
// Cache is the interface for cache.
type Cache interface {
// Adds a value to the cache.
Add(key Key, value interface{}) interface{}
// Returns key's value from the cache.
Get(key Key) (interface{}, bool)
// Checks if a key exists in cache.
Contains(key Key) bool
// Removes a key from the cache.
Remove(key Key) interface{}
// Returns the number of items in the cache.
Len() int
// Clears all cache entries.
Clear()
}
// LRUCache is a simple LRU cache.
type LRUCache struct {
// Size is the maximum number of entries before an item is evicted.
// Zero means no limit on the number of entries.
Size uint
ll *list.List
cache map[interface{}]*list.Element
}
type entry struct {
key Key
value interface{}
}
// Add adds a value to the cache and updates the "recently used"-ness of the key.
func (c *LRUCache) Add(key Key, value interface{}) interface{} {
if c.cache == nil {
c.cache = make(map[interface{}]*list.Element)
c.ll = list.New()
}
if e, ok := c.cache[key]; ok {
c.ll.MoveToFront(e)
value, e.Value.(*entry).value = e.Value.(*entry).value, value
return value
}
e := c.ll.PushFront(&entry{key, value})
c.cache[key] = e
if c.Size != 0 && uint(c.ll.Len()) > c.Size {
v := c.ll.Remove(c.ll.Back())
delete(c.cache, v.(*entry).key)
}
return nil
}
// Get returns key's value from the cache and updates the "recently used"-ness.
func (c *LRUCache) Get(key Key) (interface{}, bool) {
if c.cache == nil {
return nil, false
}
if e, ok := c.cache[key]; ok {
c.ll.MoveToFront(e)
return e.Value.(*entry).value, true
}
return nil, false
}
// Contains checks if a key exists in cache without updating the recent-ness.
func (c *LRUCache) Contains(key Key) bool {
if c.cache == nil {
return false
}
_, ok := c.cache[key]
return ok
}
// Remove removes a key from the cache.
func (c *LRUCache) Remove(key Key) interface{} {
if c.cache == nil {
return nil
}
if e, ok := c.cache[key]; ok {
c.ll.Remove(e)
delete(c.cache, key)
return e.Value.(*entry).value
}
return nil
}
// Len returns the number of items in the cache.
func (c *LRUCache) Len() int {
if c.cache == nil {
return 0
}
return c.ll.Len()
}
// Clear clears all cache entries.
func (c *LRUCache) Clear() {
c.ll = nil
c.cache = nil
}