@@ -3,16 +3,15 @@ package internal
33import (
44 "container/heap"
55 "fmt"
6- "strconv"
76 "time"
87)
98
109// Op describes a set of cache operations.
11- type Op int
10+ type Op uint8
1211
1312// These are the generalized cache operations that can trigger a event.
1413const (
15- Read Op = iota
14+ Read Op = iota + 1
1615 Write
1716 Remove
1817 maxOp
@@ -31,6 +30,22 @@ func (op Op) String() string {
3130 }
3231}
3332
33+ type handler struct {
34+ mask [((maxOp - 1 ) + 7 ) / 8 ]uint8
35+ }
36+
37+ func (h * handler ) want (op Op ) bool {
38+ return (h .mask [op / 8 ]>> uint8 (op & 7 ))& 1 != 0
39+ }
40+
41+ func (h * handler ) set (op Op ) {
42+ h .mask [op / 8 ] |= 1 << uint8 (op & 7 )
43+ }
44+
45+ func (h * handler ) clear (op Op ) {
46+ h .mask [op / 8 ] &^= 1 << uint8 (op & 7 )
47+ }
48+
3449// Collection represents the cache underlying data structure,
3550// and defines the functions or operations that can be applied to the data elements.
3651type Collection interface {
@@ -77,7 +92,7 @@ type Cache struct {
7792 coll Collection
7893 heap expiringHeap
7994 entries map [interface {}]* Entry
80- events [ maxOp ][] func ( Event )
95+ handlers map [ chan <- Event ] * handler
8196 ttl time.Duration
8297 capacity int
8398}
@@ -165,7 +180,7 @@ func (c *Cache) Update(key, value interface{}) {
165180func (c * Cache ) Purge () {
166181 defer c .coll .Init ()
167182
168- if len (c .events [ Remove ] ) == 0 {
183+ if len (c .handlers ) == 0 {
169184 c .entries = make (map [interface {}]* Entry )
170185 c .heap = nil
171186 return
@@ -260,8 +275,14 @@ func (c *Cache) emit(op Op, k, v interface{}, exp time.Time, ok bool) {
260275 Ok : ok ,
261276 }
262277
263- for _ , fn := range c .events [op ] {
264- fn (e )
278+ for c , h := range c .handlers {
279+ if h .want (op ) {
280+ // send but do not block for it
281+ select {
282+ case c <- e :
283+ default :
284+ }
285+ }
265286 }
266287}
267288
@@ -304,38 +325,58 @@ func (c *Cache) Cap() int {
304325 return c .capacity
305326}
306327
307- // Notify causes cahce to relay events to fn .
308- // If no operations are provided, all incoming operations will be relayed to fn .
328+ // Notify causes cache to relay events to ch .
329+ // If no operations are provided, all incoming operations will be relayed to ch .
309330// Otherwise, just the provided operations will.
310- func (c * Cache ) Notify (fn func (Event ), ops ... Op ) {
331+ func (c * Cache ) Notify (ch chan <- Event , ops ... Op ) {
332+ if ch == nil {
333+ panic ("libcache: Notify using nil channel" )
334+ }
335+
336+ h := new (handler )
337+ c .handlers [ch ] = h
338+
339+ if len (ops ) == 0 {
340+ for i := 1 ; i <= int (maxOp ); i ++ {
341+ h .set (Op (i ))
342+ }
343+ return
344+ }
345+
346+ for _ , op := range ops {
347+ h .set (op )
348+ }
349+ }
350+
351+ // Ignore causes the provided ops to be ignored. Ignore undoes the effect
352+ // of any prior calls to Notify for the provided ops.
353+ // If no ops are provided, ch removed.
354+ func (c * Cache ) Ignore (ch chan <- Event , ops ... Op ) {
311355 if len (ops ) == 0 {
312- ops = append (ops , Read , Write , Remove )
356+ delete (c .handlers , ch )
357+ return
358+ }
359+
360+ h , ok := c .handlers [ch ]
361+ if ! ok {
362+ return
313363 }
314364
315365 for _ , op := range ops {
316- if op < 0 && op >= maxOp {
317- panic ("libcache: notify on unknown operation #" + strconv .Itoa (int (op )))
318- }
319- c .events [op ] = append (c .events [op ], fn )
366+ h .clear (op )
320367 }
321368}
322369
323370// RegisterOnEvicted registers a function,
324371// to call it when an entry is purged from the cache.
325372func (c * Cache ) RegisterOnEvicted (fn func (key , value interface {})) {
326- c .Notify (func (e Event ) {
327- fn (e .Key , e .Value )
328- }, Remove )
373+ panic ("RegisterOnEvicted no longer available" )
329374}
330375
331376// RegisterOnExpired registers a function,
332377// to call it when an entry TTL elapsed.
333378func (c * Cache ) RegisterOnExpired (fn func (key , value interface {})) {
334- c .Notify (func (e Event ) {
335- if e .Expiry .Before (time .Now ()) {
336- fn (e .Key , e .Value )
337- }
338- }, Remove )
379+ panic ("RegisterOnExpired no longer available" )
339380}
340381
341382// New return new abstracted cache.
@@ -344,6 +385,7 @@ func New(c Collection, cap int) *Cache {
344385 coll : c ,
345386 capacity : cap ,
346387 entries : make (map [interface {}]* Entry ),
388+ handlers : make (map [chan <- Event ]* handler ),
347389 }
348390}
349391
0 commit comments