diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-03-29 21:03:37 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-03-29 22:49:02 -0600 |
commit | ab6f5d5d783f7fb211aa759a0e01ec716b58ccef (patch) | |
tree | da25c8f52d6b986e441abbef5af2bcbf8bb1e58d /lib/containers/lrucache.go | |
parent | c882629607b10487777240d94b9b754c96c9b13f (diff) |
containers: Fix some issues with ARCache
Diffstat (limited to 'lib/containers/lrucache.go')
-rw-r--r-- | lib/containers/lrucache.go | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/lib/containers/lrucache.go b/lib/containers/lrucache.go index 2ea1989..5c51435 100644 --- a/lib/containers/lrucache.go +++ b/lib/containers/lrucache.go @@ -73,19 +73,24 @@ func (c *lruCache[K, V]) waitForAvail() { ch := make(chan struct{}) c.waiters.Store(&LinkedListEntry[chan struct{}]{Value: ch}) c.mu.Unlock() - <-ch - c.mu.Lock() + <-ch // receive the lock from .Release() + if c.unused.IsEmpty() && c.evictable.IsEmpty() { + panic(fmt.Errorf("should not happen: waitForAvail is returning, but nothing is available")) + } } -// notifyAvail is called when an entry becomes unused or evictable, -// and wakes up the highest-priority .waitForAvail() waiter (if there -// is one). -func (c *lruCache[K, V]) notifyAvail() { +// unlockAndNotifyAvail is called when an entry becomes unused or +// evictable, and wakes up the highest-priority .waitForAvail() waiter +// (if there is one). +func (c *lruCache[K, V]) unlockAndNotifyAvail() { waiter := c.waiters.Oldest if waiter == nil { + c.mu.Unlock() return } c.waiters.Delete(waiter) + // We don't actually unlock, we're "transferring" the lock to + // the waiter. close(waiter.Value) } @@ -171,8 +176,8 @@ func (c *lruCache[K, V]) Delete(k K) { c.evictable.Delete(entry) c.unused.Store(entry) - // No need to call c.notifyAvail(); if we were able to delete - // it, it was already available. + // No need to call c.unlockAndNotifyAvail(); if we were able + // to delete it, it was already available. c.mu.Unlock() } @@ -180,7 +185,6 @@ func (c *lruCache[K, V]) Delete(k K) { // Release implements the 'Cache' interface. func (c *lruCache[K, V]) Release(k K) { c.mu.Lock() - defer c.mu.Unlock() entry := c.byName[k] if entry == nil || entry.Value.refs <= 0 { @@ -196,7 +200,9 @@ func (c *lruCache[K, V]) Release(k K) { } else { c.evictable.Store(entry) } - c.notifyAvail() + c.unlockAndNotifyAvail() + } else { + c.mu.Unlock() } } |