From 8142b23bcb507456fab812889987b859e04ab22e Mon Sep 17 00:00:00 2001 From: rjbasitali Date: Tue, 5 Apr 2022 04:10:40 +0500 Subject: [PATCH] cache eviction using sweeper --- delete_expired.go | 15 +++++++++++++++ flush.go | 8 ++++++++ my_cache.go | 22 ++++++++++++++++++++-- set.go | 2 +- sweeper.go | 32 ++++++++++++++++++++++++++++++++ value.go | 14 +++++++++----- 6 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 delete_expired.go create mode 100644 flush.go create mode 100644 sweeper.go diff --git a/delete_expired.go b/delete_expired.go new file mode 100644 index 0000000..954360c --- /dev/null +++ b/delete_expired.go @@ -0,0 +1,15 @@ +package gocache + +import "time" + +func (cache *myCache) deleteExpired() { + cache.mutex.Lock() + defer cache.mutex.Unlock() + + now := time.Now().UnixNano() + for k, v := range cache.items { + if v.expiration > 0 && now > v.expiration { + delete(cache.items, k) + } + } +} diff --git a/flush.go b/flush.go new file mode 100644 index 0000000..3c0c882 --- /dev/null +++ b/flush.go @@ -0,0 +1,8 @@ +package gocache + +func (cache *myCache) Flush() { + cache.mutex.Lock() + defer cache.mutex.Unlock() + + cache.items = make(map[string]*value) +} diff --git a/my_cache.go b/my_cache.go index 89348d1..3e115fc 100644 --- a/my_cache.go +++ b/my_cache.go @@ -1,12 +1,15 @@ package gocache import ( + "runtime" "sync" + "time" ) type myCache struct { - mutex sync.Mutex - items map[string]*value + mutex sync.Mutex + items map[string]*value + expireAfter int64 } func NewCache() Cache { @@ -14,3 +17,18 @@ func NewCache() Cache { items: make(map[string]*value), } } + +func NewCacheWithSweeper(interval, expireAfter time.Duration) Cache { + c := &myCache{ + items: make(map[string]*value), + expireAfter: expireAfter.Nanoseconds(), + } + + if interval > 0 && expireAfter > 0 { + s := newSweeper(c, interval) + runtime.SetFinalizer(c, s.stopSweeper) + go s.run(c) + } + + return c +} diff --git a/set.go b/set.go index eceff2a..bf58b52 100644 --- a/set.go +++ b/set.go @@ -4,7 +4,7 @@ func (cache *myCache) Set(key string, data interface{}) error { cache.mutex.Lock() defer cache.mutex.Unlock() - value := newValue(key, data) + value := newValue(key, data, cache.expireAfter) cache.items[key] = value return nil diff --git a/sweeper.go b/sweeper.go new file mode 100644 index 0000000..c840af9 --- /dev/null +++ b/sweeper.go @@ -0,0 +1,32 @@ +package gocache + +import "time" + +type sweeper struct { + Interval time.Duration + stop chan bool +} + +func (s *sweeper) run(c *myCache) { + ticker := time.NewTicker(s.Interval) + for { + select { + case <-ticker.C: + c.deleteExpired() + case <-s.stop: + ticker.Stop() + return + } + } +} + +func newSweeper(c *myCache, i time.Duration) *sweeper { + return &sweeper{ + Interval: i, + stop: make(chan bool), + } +} + +func (s *sweeper) stopSweeper() { + s.stop <- true +} diff --git a/value.go b/value.go index 4aaad8f..bc15281 100644 --- a/value.go +++ b/value.go @@ -1,13 +1,17 @@ package gocache +import "time" + type value struct { - key string - data interface{} + key string + data interface{} + expiration int64 } -func newValue(key string, data interface{}) *value { +func newValue(key string, data interface{}, expiration int64) *value { return &value{ - key: key, - data: data, + key: key, + data: data, + expiration: time.Now().UnixNano() + expiration, } }