Skip to content

Commit

Permalink
fix: race in close function (#384)
Browse files Browse the repository at this point in the history
Fixes: #377
  • Loading branch information
StarpTech authored Jul 23, 2024
1 parent 21593c1 commit f599748
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# IDE
.idea
.vscode
16 changes: 8 additions & 8 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type Cache[K Key, V any] struct {
// stop is used to stop the processItems goroutine.
stop chan struct{}
// indicates whether cache is closed.
isClosed bool
isClosed atomic.Bool
// cost calculates cost from a value.
cost func(value V) int64
// ignoreInternalCost dictates whether to ignore the cost of internally storing
Expand Down Expand Up @@ -221,7 +221,7 @@ func NewCache[K Key, V any](config *Config[K, V]) (*Cache[K, V], error) {
// Wait blocks until all buffered writes have been applied. This ensures a call to Set()
// will be visible to future calls to Get().
func (c *Cache[K, V]) Wait() {
if c == nil || c.isClosed {
if c == nil || c.isClosed.Load() {
return
}
wg := &sync.WaitGroup{}
Expand All @@ -234,7 +234,7 @@ func (c *Cache[K, V]) Wait() {
// value was found or not. The value can be nil and the boolean can be true at
// the same time. Get will not return expired items.
func (c *Cache[K, V]) Get(key K) (V, bool) {
if c == nil || c.isClosed {
if c == nil || c.isClosed.Load() {
return zeroValue[V](), false
}
keyHash, conflictHash := c.keyToHash(key)
Expand Down Expand Up @@ -267,7 +267,7 @@ func (c *Cache[K, V]) Set(key K, value V, cost int64) bool {
// expires, which is identical to calling Set. A negative value is a no-op and the value
// is discarded.
func (c *Cache[K, V]) SetWithTTL(key K, value V, cost int64, ttl time.Duration) bool {
if c == nil || c.isClosed {
if c == nil || c.isClosed.Load() {
return false
}

Expand Down Expand Up @@ -316,7 +316,7 @@ func (c *Cache[K, V]) SetWithTTL(key K, value V, cost int64, ttl time.Duration)

// Del deletes the key-value item from the cache if it exists.
func (c *Cache[K, V]) Del(key K) {
if c == nil || c.isClosed {
if c == nil || c.isClosed.Load() {
return
}
keyHash, conflictHash := c.keyToHash(key)
Expand Down Expand Up @@ -363,7 +363,7 @@ func (c *Cache[K, V]) GetTTL(key K) (time.Duration, bool) {

// Close stops all goroutines and closes all channels.
func (c *Cache[K, V]) Close() {
if c == nil || c.isClosed {
if c == nil || c.isClosed.Load() {
return
}
c.Clear()
Expand All @@ -374,14 +374,14 @@ func (c *Cache[K, V]) Close() {
close(c.setBuf)
c.cachePolicy.Close()
c.cleanupTicker.Stop()
c.isClosed = true
c.isClosed.Store(true)
}

// Clear empties the hashmap and zeroes all cachePolicy counters. Note that this is
// not an atomic operation (but that shouldn't be a problem as it's assumed that
// Set/Get calls won't be occurring until after this).
func (c *Cache[K, V]) Clear() {
if c == nil || c.isClosed {
if c == nil || c.isClosed.Load() {
return
}
// Block until processItems goroutine is returned.
Expand Down

0 comments on commit f599748

Please sign in to comment.