Skip to content

Commit 5b5ae2b

Browse files
committed
use WaitGroup in event functions
1 parent 2efccf6 commit 5b5ae2b

File tree

2 files changed

+228
-107
lines changed

2 files changed

+228
-107
lines changed

cache.go

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package ttlcache
22

33
import (
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

Comments
 (0)