Partially fixing #3.

On close, drain the deletables channel (unblocking an waiting goroutines) and
close deletables. Like Gets and Sets against a now-closed promotables,
this means any subsequent to Deletes from deletables will panic.

I'm still not sure that this is ccache's responsibility. If a client closes a DB
connection, we'd expect subsequent operations against the now-closed connection
to fail. My main problems with defer'ing a recover are:

1 - the performance overhead on every single get / set / delete
2 - not communicating with the caller that the requested operatin is no longer
    valid.
This commit is contained in:
Karl Seguin
2015-07-26 11:05:48 +08:00
parent bfa769c6b6
commit 74754c77cc

View File

@@ -150,20 +150,35 @@ func (c *Cache) worker() {
select { select {
case item, ok := <-c.promotables: case item, ok := <-c.promotables:
if ok == false { if ok == false {
return goto drain
} }
if c.doPromote(item) && c.size > c.maxSize { if c.doPromote(item) && c.size > c.maxSize {
c.gc() c.gc()
} }
case item := <-c.deletables: case item := <-c.deletables:
c.doDelete(item)
}
}
drain:
for {
select {
case item := <-c.deletables:
c.doDelete(item)
default:
close(c.deletables)
return
}
}
}
func (c *Cache) doDelete(item *Item) {
if item.element == nil { if item.element == nil {
item.promotions = -2 item.promotions = -2
} else { } else {
c.size -= item.size c.size -= item.size
c.list.Remove(item.element) c.list.Remove(item.element)
} }
}
}
} }
func (c *Cache) doPromote(item *Item) bool { func (c *Cache) doPromote(item *Item) bool {