@@ -41,16 +41,27 @@ func NewCache[K comparable, V any](size int) *Cache[K, V] {
4141
4242func (c * Cache [K , V ]) Put (key K , value V ) {
4343 c .lock .Lock ()
44- defer c .lock .Unlock ()
44+
45+ var evictedKey K
46+ var evictedValue V
47+ evicted := false
4548
4649 if c .elements .Len () == c .size {
47- oldestKey , oldestValue , _ := c .elements .Oldest ()
50+ oldestKey , oldestValue , ok := c .elements .Oldest ()
4851 c .elements .Delete (oldestKey )
49- if c .onEvict != nil {
50- c .onEvict (oldestKey , oldestValue )
52+ if ok {
53+ evicted = true
54+ evictedKey = oldestKey
55+ evictedValue = oldestValue
5156 }
5257 }
5358 c .elements .Put (key , value )
59+ c .lock .Unlock ()
60+
61+ // unlock before calling onEvict to avoid deadlocks
62+ if evicted && c .onEvict != nil {
63+ c .onEvict (evictedKey , evictedValue )
64+ }
5465}
5566
5667func (c * Cache [K , V ]) Get (key K ) (V , bool ) {
@@ -65,29 +76,38 @@ func (c *Cache[K, V]) Get(key K) (V, bool) {
6576 return val , true
6677}
6778
68- func (c * Cache [K , _ ]) Evict (key K ) {
79+ func (c * Cache [K , V ]) Evict (key K ) {
6980 c .lock .Lock ()
70- defer c .lock .Unlock ()
71- c .elements .Delete (key )
81+
82+ var evictedValue V
83+ var found bool
7284 if c .onEvict != nil {
73- value , _ := c .elements .Get (key )
74- c .onEvict (key , value )
85+ evictedValue , found = c .elements .Get (key )
86+ }
87+ c .elements .Delete (key )
88+ c .lock .Unlock ()
89+
90+ if found {
91+ c .onEvict (key , evictedValue )
7592 }
7693}
7794
78- func (c * Cache [_ , _ ]) Flush () {
95+ func (c * Cache [K , V ]) Flush () {
7996 c .lock .Lock ()
80- defer c .lock .Unlock ()
81-
82- // Call onEvict for each element before clearing
97+ var evicted map [K ]V
8398 if c .onEvict != nil {
99+ evicted = make (map [K ]V , c .elements .Len ())
84100 iter := c .elements .NewIterator ()
85101 for iter .Next () {
86- c . onEvict ( iter .Key (), iter .Value () )
102+ evicted [ iter .Key ()] = iter .Value ()
87103 }
88104 }
89-
90105 c .elements .Clear ()
106+ c .lock .Unlock ()
107+
108+ for key , value := range evicted {
109+ c .onEvict (key , value )
110+ }
91111}
92112
93113func (c * Cache [_ , _ ]) Len () int {
0 commit comments