-
Notifications
You must be signed in to change notification settings - Fork 212
/
doublecache.go
59 lines (53 loc) · 1.51 KB
/
doublecache.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
package types
import (
"sync"
)
// DoubleCache is a structure for storing which keys have been encountered before. It's initialized with a size and it
// stores between size and 2*size keys. Every time the cache size reaches 2*size and a new value is added, the oldest
// size keys are discarded and the size drops back to size.
// DoubleCache is thread safe.
type DoubleCache struct {
size uint
cacheA map[Hash12]struct{}
cacheB map[Hash12]struct{}
cacheMutex sync.RWMutex
}
// NewDoubleCache returns a new DoubleCache.
func NewDoubleCache(size uint) *DoubleCache {
return &DoubleCache{size: size, cacheA: make(map[Hash12]struct{}, size), cacheB: make(map[Hash12]struct{}, size)}
}
// GetOrInsert checks if a value is already in the cache, otherwise it adds it. Returns bool whether or not the value
// was found in the cache (true - already in cache, false - wasn't in cache before this was called).
func (a *DoubleCache) GetOrInsert(key Hash12) bool {
a.cacheMutex.Lock()
defer a.cacheMutex.Unlock()
if a.get(key) {
return true
}
a.insert(key)
return false
}
func (a *DoubleCache) get(key Hash12) bool {
_, ok := a.cacheA[key]
if ok {
return true
}
_, ok = a.cacheB[key]
if ok {
return true
}
return false
}
func (a *DoubleCache) insert(key Hash12) {
if uint(len(a.cacheA)) < a.size {
a.cacheA[key] = struct{}{}
return
}
if uint(len(a.cacheB)) < a.size {
a.cacheB[key] = struct{}{}
return
}
a.cacheA = a.cacheB
a.cacheB = make(map[Hash12]struct{}, a.size)
a.cacheB[key] = struct{}{}
}