@@ -21,11 +21,15 @@ type Cache[K comparable, V any] struct {
21
21
elements * linked.Hashmap [K , V ]
22
22
size int
23
23
24
- // onEvict is called with the key and value of an evicted entry, if set.
24
+ // onEvict is called with the key and value of an entry before eviction , if set.
25
25
onEvict func (K , V )
26
26
}
27
27
28
- // SetOnEvict sets a callback to be called with the key and value of an evicted entry.
28
+ // SetOnEvict sets a callback to be called with the key and value of an entry before eviction.
29
+ // The onEvict callback is called while holding the cache lock.
30
+ // Do not call any cache methods (Get, Put, Evict, Flush) from within the callback
31
+ // as this will cause a deadlock. The callback should only be used for cleanup
32
+ // operations like closing files or releasing resources.
29
33
func (c * Cache [K , V ]) SetOnEvict (cb func (K , V )) {
30
34
c .lock .Lock ()
31
35
defer c .lock .Unlock ()
@@ -44,11 +48,11 @@ func (c *Cache[K, V]) Put(key K, value V) {
44
48
defer c .lock .Unlock ()
45
49
46
50
if c .elements .Len () == c .size {
47
- oldestKey , oldestValue , _ := c .elements .Oldest ()
48
- c .elements .Delete (oldestKey )
49
- if c .onEvict != nil {
51
+ oldestKey , oldestValue , found := c .elements .Oldest ()
52
+ if c .onEvict != nil && found {
50
53
c .onEvict (oldestKey , oldestValue )
51
54
}
55
+ c .elements .Delete (oldestKey )
52
56
}
53
57
c .elements .Put (key , value )
54
58
}
@@ -68,11 +72,12 @@ func (c *Cache[K, V]) Get(key K) (V, bool) {
68
72
func (c * Cache [K , _ ]) Evict (key K ) {
69
73
c .lock .Lock ()
70
74
defer c .lock .Unlock ()
71
- c .elements .Delete (key )
72
75
if c .onEvict != nil {
73
- value , _ := c .elements .Get (key )
74
- c .onEvict (key , value )
76
+ if value , found := c .elements .Get (key ); found {
77
+ c .onEvict (key , value )
78
+ }
75
79
}
80
+ c .elements .Delete (key )
76
81
}
77
82
78
83
func (c * Cache [_ , _ ]) Flush () {
0 commit comments