-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmemcache.go
80 lines (69 loc) · 1.72 KB
/
memcache.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
package memcache
import (
"sync"
"time"
)
const (
defaultTimeout = 30 * time.Minute
defaultNumberOfShard int = 1 << 8
mask = 255 // 0xFF
)
type Stringer interface {
~string
}
// Cache represent the memory cache
type Cache[K Stringer, V any] struct {
shards [defaultNumberOfShard]shard[K, V]
mu [defaultNumberOfShard]sync.Mutex
}
type item[V any] struct {
expiredAt time.Time
value V
}
// NewCache creates a memory cache
func NewCache[K Stringer, V any]() Cache[K,V] {
newCache := Cache[K, V]{}
for i := range newCache.shards {
newCache.shards[i].hashmap = make(map[K]item[V])
}
return &newCache
}
// Set the value with the key
func (c *Cache[K Stringer, V any]) Set(key K, value V) {
hashKey := hashString(key)
shardIdx := hashKey & mask
c.mu[shardIdx].Lock()
defer c.mu[shardIdx].Unlock()
c.shards[shardIdx].set(key, value, defaultTimeout)
}
func (c *Cache[K Stringer, V any]) SetUntil(key K, value V, d time.Duration) {
if d <= 0 {
return
}
hashKey := hashString(key)
shardIdx := hashKey & mask
c.mu[shardIdx].Lock()
c.shards[shardIdx].set(key, value, d)
c.mu[shardIdx].Unlock()
}
func (c *Cache[K Stringer, V any]) Get(key K) (value V) {
hashKey := hashString(key)
shardIdx := hashKey & mask
c.mu[shardIdx].Lock()
defer c.mu[shardIdx].Unlock()
return c.shards[shardIdx].get(key)
}
func (c *Cache[K Stringer, V any]) Take(key K) (value V) {
hashKey := hashString(key)
shardIdx := hashKey & mask
c.mu[shardIdx].Lock()
defer c.mu[shardIdx].Unlock()
return c.shards[shardIdx].take(key)
}
func (c *Cache[K Stringer, V any]) Del(key K) {
hashKey := hashString(key)
shardIdx := hashKey & mask
c.mu[shardIdx].Lock()
c.shards[shardIdx].delete(key)
c.mu[shardIdx].Unlock()
}