Ability to dynamically SetMaxSize

To support this, rather than adding another field/channel like
`getDroppedReq`, I added a `control` channel that can be used for these
miscellaneous interactions with the worker. The control can also be
used to take over for the `donec` channel
This commit is contained in:
Karl Seguin
2020-06-26 20:22:30 +08:00
parent d9aec58960
commit 40275a30c8
4 changed files with 135 additions and 38 deletions

View File

@@ -10,15 +10,13 @@ import (
type LayeredCache struct {
*Configuration
list *list.List
buckets []*layeredBucket
bucketMask uint32
size int64
deletables chan *Item
promotables chan *Item
donec chan struct{}
getDroppedReq chan struct{}
getDroppedRes chan int
list *list.List
buckets []*layeredBucket
bucketMask uint32
size int64
deletables chan *Item
promotables chan *Item
control chan interface{}
}
// Create a new layered cache with the specified configuration.
@@ -41,8 +39,7 @@ func Layered(config *Configuration) *LayeredCache {
bucketMask: uint32(config.buckets) - 1,
buckets: make([]*layeredBucket, config.buckets),
deletables: make(chan *Item, config.deleteBuffer),
getDroppedReq: make(chan struct{}),
getDroppedRes: make(chan int),
control: make(chan interface{}),
}
for i := 0; i < int(config.buckets); i++ {
c.buckets[i] = &layeredBucket{
@@ -163,19 +160,26 @@ func (c *LayeredCache) Clear() {
func (c *LayeredCache) Stop() {
close(c.promotables)
<-c.donec
<-c.control
}
// Gets the number of items removed from the cache due to memory pressure since
// the last time GetDropped was called
func (c *LayeredCache) GetDropped() int {
c.getDroppedReq <- struct{}{}
return <-c.getDroppedRes
res := make(chan int)
c.control <- getDropped{res: res}
return <-res
}
// Sets a new max size. That can result in a GC being run if the new maxium size
// is smaller than the cached size
func (c *LayeredCache) SetMaxSize(size int64) {
c.control <- setMaxSize{size}
}
func (c *LayeredCache) restart() {
c.promotables = make(chan *Item, c.promoteBuffer)
c.donec = make(chan struct{})
c.control = make(chan interface{})
go c.worker()
}
@@ -199,7 +203,7 @@ func (c *LayeredCache) promote(item *Item) {
}
func (c *LayeredCache) worker() {
defer close(c.donec)
defer close(c.control)
dropped := 0
for {
select {
@@ -220,9 +224,17 @@ func (c *LayeredCache) worker() {
}
c.list.Remove(item.element)
}
case _ = <-c.getDroppedReq:
c.getDroppedRes <- dropped
dropped = 0
case control := <-c.control:
switch msg := control.(type) {
case getDropped:
msg.res <- dropped
dropped = 0
case setMaxSize:
c.maxSize = msg.size
if c.size > c.maxSize {
dropped += c.gc()
}
}
}
}
}