diff --git a/go.mod b/go.mod index 2260f65..8e8e9ef 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module git.wntrmute.dev/kyle/go-mru go 1.17 + +require github.com/benbjohnson/clock v1.3.5 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ee6593c --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/mru.go b/mru.go index 2aa0cc2..b0826b8 100644 --- a/mru.go +++ b/mru.go @@ -30,7 +30,7 @@ type Cache struct { // New must be used to create a new Cache. func New(cap int) *Cache { return &Cache{ - store: map[string]*Item{}, + store: map[string]*item{}, access: newTimestamps(cap), cap: cap, clock: clock.New(), @@ -39,11 +39,11 @@ func New(cap int) *Cache { } func (c *Cache) lock() { - m.mtx.lock() + c.mtx.Lock() } func (c *Cache) unlock() { - m.mtx.unlock() + c.mtx.Unlock() } // Len returns the number of items currently in the cache. @@ -53,6 +53,10 @@ func (c *Cache) Len() int { // evict should remove the least-recently-used cache item. func (c *Cache) evict() { + if c.access.Len() == 0 { + return + } + k := c.access.K(0) c.evictKey(k) } @@ -79,8 +83,8 @@ func (c *Cache) sanityCheck() { // data structures are consistent. It is not normally required, and it // is primarily used in testing. func (c *Cache) ConsistencyCheck() error { - m.lock() - defer m.unlock() + c.lock() + defer c.unlock() if err := c.access.ConsistencyCheck(); err != nil { return err } @@ -111,8 +115,8 @@ func (c *Cache) ConsistencyCheck() error { // Store adds the value v to the cache under the k. func (c *Cache) Store(k string, v interface{}) { - m.lock() - defer m.unlock() + c.lock() + defer c.unlock() c.sanityCheck() @@ -124,7 +128,7 @@ func (c *Cache) Store(k string, v interface{}) { c.evictKey(k) } - itm := &Item{ + itm := &item{ V: v, access: c.clock.Now().UnixNano(), } @@ -136,8 +140,8 @@ func (c *Cache) Store(k string, v interface{}) { // Get returns the value stored in the cache. If the item isn't present, // it will return false. func (c *Cache) Get(k string) (interface{}, bool) { - m.lock() - defer m.unlock() + c.lock() + defer c.unlock() c.sanityCheck() diff --git a/mru_test.go b/mru_test.go index d823b5b..9488981 100644 --- a/mru_test.go +++ b/mru_test.go @@ -20,6 +20,11 @@ func TestBasicCacheEviction(t *testing.T) { t.Fatal("cache should have size 0") } + c.evict() + if err := c.ConsistencyCheck(); err != nil { + t.Fatal(err) + } + c.Store("raven", 1) if err := c.ConsistencyCheck(); err != nil { t.Fatal(err)