-
Notifications
You must be signed in to change notification settings - Fork 2
/
lru.go
86 lines (78 loc) · 1.96 KB
/
lru.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Package gCache implements an LRU cache in golang.
// Set: Add the item both in queue and HashMap. If they capacity is full,
// it removes the least recently used element.
//
// Get: Returns the item requested via Key. On querying the item it comes
// to forward of the queue
package gCache
import (
"errors"
"sync"
"time"
)
// Cache is an object which will hold items, it is the cache of these items.
type Cache struct {
capacity int
items map[string]*cacheItem
mu sync.Mutex
}
type cacheItem struct {
value string
lastUse int64
}
// Create a new cache object.
func New(c int) *Cache {
return &Cache{
capacity: c,
items: make(map[string]*cacheItem),
mu: sync.Mutex{},
}
}
// Set a key into the cache, remove the last used key if capacity has been met.
func (c *Cache) Set(key string, val string) {
c.mu.Lock()
defer c.mu.Unlock()
// Search for the key in map, if the key isn't there
// add it, no action if the key already exists.
if _, ok := c.items[key]; !ok {
// Check the capacity
now := time.Now().UnixNano()
if len(c.items) == c.capacity { // Time to evict
// Get the least use item from the queue
var lu int64
var del string
for key, i := range c.items {
switch {
case lu == 0:
// First time set lu to item lastUse
lu = i.lastUse
del = key
continue
case lu > i.lastUse:
// Current item is older than lu swap.
lu = i.lastUse
del = key
continue
}
}
// The del key should be delete from the map.
delete(c.items, del)
}
// Add the new element to the cache.
c.items[key] = &cacheItem{
value: val,
lastUse: now,
}
}
}
// Get a key from the cache, update that key's lastUsed time as an artifact.
func (c *Cache) Get(k string) (string, error) {
//Search the key in map
c.mu.Lock()
defer c.mu.Unlock()
if v, ok := c.items[k]; ok {
v.lastUse = time.Now().UnixNano()
return v.value, nil
}
return "", errors.New("Key not found")
}