@@ -2,20 +2,24 @@ package evcache
2
2
3
3
import (
4
4
"sync"
5
+ "sync/atomic"
5
6
"time"
6
7
7
8
"github.com/mgnsk/list"
8
9
)
9
10
10
- type recordList [V any ] struct {
11
- list.ListOf [record [V ], * record [V ]]
11
+ type record [V any ] struct {
12
+ value V
13
+ deadline int64
14
+ wg sync.WaitGroup
15
+ initialized atomic.Bool
12
16
}
13
17
14
18
type backend [K comparable , V any ] struct {
15
19
timer * time.Timer
16
20
done chan struct {}
17
- xmap backendMap [K , * record [V ]]
18
- list recordList [ V ]
21
+ xmap backendMap [K , * list. Element [ record [V ] ]]
22
+ list list. List [ record [ V ] ]
19
23
earliestExpireAt int64
20
24
cap int
21
25
once sync.Once
@@ -29,7 +33,7 @@ func newBackend[K comparable, V any](capacity int) *backend[K, V] {
29
33
return & backend [K , V ]{
30
34
timer : t ,
31
35
done : make (chan struct {}),
32
- xmap : make (builtinMap [K , * record [V ]], capacity ),
36
+ xmap : make (builtinMap [K , * list. Element [ record [V ] ]], capacity ),
33
37
cap : capacity ,
34
38
}
35
39
}
@@ -39,66 +43,66 @@ func (b *backend[K, V]) close() error {
39
43
return nil
40
44
}
41
45
42
- func (b * backend [K , V ]) LoadOrStore (key K , new * record [V ]) (old * record [V ], loaded bool ) {
46
+ func (b * backend [K , V ]) LoadOrStore (key K , new * list. Element [ record [V ]] ) (old * list. Element [ record [V ] ], loaded bool ) {
43
47
b .mu .RLock ()
44
- if r , ok := b .xmap .Load (key ); ok {
48
+ if elem , ok := b .xmap .Load (key ); ok {
45
49
b .mu .RUnlock ()
46
- return r , true
50
+ return elem , true
47
51
}
48
52
b .mu .RUnlock ()
49
53
50
54
b .mu .Lock ()
51
55
defer b .mu .Unlock ()
52
56
53
- if r , ok := b .xmap .Load (key ); ok {
54
- return r , true
57
+ if elem , ok := b .xmap .Load (key ); ok {
58
+ return elem , true
55
59
}
56
60
57
61
b .xmap .Store (key , new )
58
62
59
63
return new , false
60
64
}
61
65
62
- func (b * backend [K , V ]) Range (f func (key K , r * record [V ]) bool ) {
66
+ func (b * backend [K , V ]) Range (f func (key K , r * list. Element [ record [V ] ]) bool ) {
63
67
b .mu .RLock ()
64
68
keys := make ([]K , 0 , b .xmap .Len ())
65
- b .xmap .Range (func (key K , _ * record [V ]) bool {
69
+ b .xmap .Range (func (key K , _ * list. Element [ record [V ] ]) bool {
66
70
keys = append (keys , key )
67
71
return true
68
72
})
69
73
b .mu .RUnlock ()
70
74
71
75
for _ , key := range keys {
72
76
b .mu .RLock ()
73
- r , ok := b .xmap .Load (key )
77
+ elem , ok := b .xmap .Load (key )
74
78
b .mu .RUnlock ()
75
- if ok && ! f (key , r ) {
79
+ if ok && ! f (key , elem ) {
76
80
return
77
81
}
78
82
}
79
83
}
80
84
81
- func (b * backend [K , V ]) evict (key K ) (* record [V ], bool ) {
82
- if r , ok := b .xmap .Load (key ); ok && r .initialized .Load () {
85
+ func (b * backend [K , V ]) evict (key K ) (* list. Element [ record [V ] ], bool ) {
86
+ if elem , ok := b .xmap .Load (key ); ok && elem . Value .initialized .Load () {
83
87
b .xmap .Delete (key )
84
- b .list .Remove (r )
85
- return r , true
88
+ b .list .Remove (elem )
89
+ return elem , true
86
90
}
87
91
88
92
return nil , false
89
93
}
90
94
91
- func (b * backend [K , V ]) pushBack (r * record [V ], ttl time.Duration ) {
92
- b .list .PushBack (r )
93
- r .initialized .Store (true )
95
+ func (b * backend [K , V ]) pushBack (elem * list. Element [ record [V ] ], ttl time.Duration ) {
96
+ b .list .PushBack (elem )
97
+ elem . Value .initialized .Store (true )
94
98
95
99
if n := b .overflow (); n > 0 {
96
100
b .startGCOnce ()
97
101
b .timer .Reset (0 )
98
- } else if r .deadline > 0 {
102
+ } else if elem . Value .deadline > 0 {
99
103
b .startGCOnce ()
100
- if b .earliestExpireAt == 0 || r .deadline < b .earliestExpireAt {
101
- b .earliestExpireAt = r .deadline
104
+ if b .earliestExpireAt == 0 || elem . Value .deadline < b .earliestExpireAt {
105
+ b .earliestExpireAt = elem . Value .deadline
102
106
b .timer .Reset (ttl )
103
107
}
104
108
}
@@ -124,29 +128,29 @@ func (b *backend[K, V]) runGC(now int64) {
124
128
b .mu .Lock ()
125
129
defer b .mu .Unlock ()
126
130
127
- var overflowed map [* record [V ]]bool
131
+ var overflowed map [* list. Element [ record [V ] ]]bool
128
132
129
133
if n := b .overflow (); n > 0 {
130
- overflowed = make (map [* record [V ]]bool , n )
134
+ overflowed = make (map [* list. Element [ record [V ] ]]bool , n )
131
135
132
- r := b .list .Front ()
133
- overflowed [r ] = true
136
+ elem := b .list .Front ()
137
+ overflowed [elem ] = true
134
138
135
139
for i := 1 ; i < n ; i ++ {
136
- r = r .Next ()
137
- overflowed [r ] = true
140
+ elem = elem .Next ()
141
+ overflowed [elem ] = true
138
142
}
139
143
}
140
144
141
145
var earliest int64
142
146
143
- b .xmap .Range (func (key K , r * record [V ]) bool {
144
- if r .initialized .Load () {
145
- if len (overflowed ) > 0 && overflowed [r ] || r . deadline > 0 && r .deadline < now {
147
+ b .xmap .Range (func (key K , elem * list. Element [ record [V ] ]) bool {
148
+ if elem . Value .initialized .Load () {
149
+ if len (overflowed ) > 0 && overflowed [elem ] || elem . Value . deadline > 0 && elem . Value .deadline < now {
146
150
b .xmap .Delete (key )
147
- b .list .Remove (r )
148
- } else if r . deadline > 0 && (earliest == 0 || r .deadline < earliest ) {
149
- earliest = r .deadline
151
+ b .list .Remove (elem )
152
+ } else if elem . Value . deadline > 0 && (earliest == 0 || elem . Value .deadline < earliest ) {
153
+ earliest = elem . Value .deadline
150
154
}
151
155
}
152
156
return true
0 commit comments