@@ -2,6 +2,7 @@ package ttlcache
22
33import (
44 "container/list"
5+ "context"
56 "fmt"
67 "sync"
78 "time"
@@ -157,7 +158,7 @@ func (c *Cache[K, V]) set(key K, value V, ttl time.Duration) *Item[K, V] {
157158
158159 c .events .insertion .mu .RLock ()
159160 for _ , fn := range c .events .insertion .fns {
160- go fn (item )
161+ fn (item )
161162 }
162163 c .events .insertion .mu .RUnlock ()
163164
@@ -207,7 +208,7 @@ func (c *Cache[K, V]) evict(reason EvictionReason, elems ...*list.Element) {
207208 c .items .expQueue .remove (elems [i ])
208209
209210 for _ , fn := range c .events .eviction .fns {
210- go fn (reason , item )
211+ fn (reason , item )
211212 }
212213 }
213214 c .events .eviction .mu .RUnlock ()
@@ -224,7 +225,7 @@ func (c *Cache[K, V]) evict(reason EvictionReason, elems ...*list.Element) {
224225 item := elem .Value .(* Item [K , V ])
225226
226227 for _ , fn := range c .events .eviction .fns {
227- go fn (reason , item )
228+ fn (reason , item )
228229 }
229230 }
230231 c .events .eviction .mu .RUnlock ()
@@ -438,38 +439,78 @@ func (c *Cache[K, V]) Stop() {
438439}
439440
440441// OnInsertion adds the provided function to be executed when
441- // a new item is inserted into the cache.
442- // It returns a function that may be called to delete
443- // the provided function from the list of insertion subscribers.
444- func (c * Cache [K , V ]) OnInsertion (fn func (* Item [K , V ])) func () {
442+ // a new item is inserted into the cache. The function is executed
443+ // on a separate goroutine and does not block the flow of the cache
444+ // manager.
445+ // The returned function may be called to delete the subscription function
446+ // from the list of insertion subscribers.
447+ // When the returned function is called, it blocks until all instances of
448+ // the same subscription function return. A context is used to notify the
449+ // subscription function when the returned/deletion function is called.
450+ func (c * Cache [K , V ]) OnInsertion (fn func (context.Context , * Item [K , V ])) func () {
451+ var (
452+ wg sync.WaitGroup
453+ ctx , cancel = context .WithCancel (context .Background ())
454+ )
455+
445456 c .events .insertion .mu .Lock ()
446457 id := c .events .insertion .nextID
447- c .events .insertion .fns [id ] = fn
458+ c .events .insertion .fns [id ] = func (item * Item [K , V ]) {
459+ wg .Add (1 )
460+ go func () {
461+ fn (ctx , item )
462+ wg .Done ()
463+ }()
464+ }
448465 c .events .insertion .nextID ++
449466 c .events .insertion .mu .Unlock ()
450467
451468 return func () {
469+ cancel ()
470+
452471 c .events .insertion .mu .Lock ()
453472 delete (c .events .insertion .fns , id )
454473 c .events .insertion .mu .Unlock ()
474+
475+ wg .Wait ()
455476 }
456477}
457478
458479// OnEviction adds the provided function to be executed when
459- // an item is evicted/deleted from the cache.
460- // It returns a function that may be called to delete
461- // the provided function from the list of eviction subscribers.
462- func (c * Cache [K , V ]) OnEviction (fn func (EvictionReason , * Item [K , V ])) func () {
480+ // an item is evicted/deleted from the cache. The function is executed
481+ // on a separate goroutine and does not block the flow of the cache
482+ // manager.
483+ // The returned function may be called to delete the subscription function
484+ // from the list of eviction subscribers.
485+ // When the returned function is called, it blocks until all instances of
486+ // the same subscription function return. A context is used to notify the
487+ // subscription function when the returned/deletion function is called.
488+ func (c * Cache [K , V ]) OnEviction (fn func (context.Context , EvictionReason , * Item [K , V ])) func () {
489+ var (
490+ wg sync.WaitGroup
491+ ctx , cancel = context .WithCancel (context .Background ())
492+ )
493+
463494 c .events .eviction .mu .Lock ()
464495 id := c .events .eviction .nextID
465- c .events .eviction .fns [id ] = fn
496+ c .events .eviction .fns [id ] = func (r EvictionReason , item * Item [K , V ]) {
497+ wg .Add (1 )
498+ go func () {
499+ fn (ctx , r , item )
500+ wg .Done ()
501+ }()
502+ }
466503 c .events .eviction .nextID ++
467504 c .events .eviction .mu .Unlock ()
468505
469506 return func () {
507+ cancel ()
508+
470509 c .events .eviction .mu .Lock ()
471510 delete (c .events .eviction .fns , id )
472511 c .events .eviction .mu .Unlock ()
512+
513+ wg .Wait ()
473514 }
474515}
475516
0 commit comments