2 Commits

Author SHA1 Message Date
2899885c42 linter fixes 2025-11-15 22:46:42 -08:00
b92e16fa4d Handle evictions properly when cache is empty. 2023-08-27 18:01:16 -07:00
6 changed files with 26 additions and 17 deletions

4
go.mod
View File

@@ -1,5 +1,5 @@
module git.wntrmute.dev/kyle/go-mru
go 1.17
go 1.22
require github.com/benbjohnson/clock v1.3.0
require github.com/benbjohnson/clock v1.3.5

4
go.sum
View File

@@ -1,2 +1,2 @@
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=

16
mru.go
View File

@@ -10,7 +10,7 @@ import (
)
type item struct {
V interface{}
V any
access int64
}
@@ -28,11 +28,11 @@ type Cache struct {
}
// New must be used to create a new Cache.
func New(cap int) *Cache {
func New(icap int) *Cache {
return &Cache{
store: map[string]*item{},
access: newTimestamps(cap),
cap: cap,
access: newTimestamps(icap),
cap: icap,
clock: clock.New(),
mtx: &sync.Mutex{},
}
@@ -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)
}
@@ -110,7 +114,7 @@ func (c *Cache) ConsistencyCheck() error {
}
// Store adds the value v to the cache under the k.
func (c *Cache) Store(k string, v interface{}) {
func (c *Cache) Store(k string, v any) {
c.lock()
defer c.unlock()
@@ -135,7 +139,7 @@ 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) {
func (c *Cache) Get(k string) (any, bool) {
c.lock()
defer c.unlock()

View File

@@ -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)

View File

@@ -3,6 +3,7 @@ package mru
import (
"errors"
"fmt"
"io"
"sort"
)
@@ -19,10 +20,10 @@ type timestamps struct {
cap int
}
func newTimestamps(cap int) *timestamps {
func newTimestamps(icap int) *timestamps {
return &timestamps{
ts: make([]timestamp, 0, cap),
cap: cap,
ts: make([]timestamp, 0, icap),
cap: icap,
}
}
@@ -47,7 +48,7 @@ func (ts *timestamps) Swap(i, j int) {
}
func (ts *timestamps) Find(k string) (int, bool) {
for i := 0; i < len(ts.ts); i++ {
for i := range len(ts.ts) {
if ts.ts[i].k == k {
return i, true
}
@@ -93,8 +94,8 @@ func (ts *timestamps) Delete(i int) {
ts.ts = append(ts.ts[:i], ts.ts[i+1:]...)
}
func (ts *timestamps) Dump() {
func (ts *timestamps) Dump(w io.Writer) {
for i := range ts.ts {
fmt.Printf("%d: %s, %d\n", i, ts.K(i), ts.T(i))
fmt.Fprintf(w, "%d: %s, %d\n", i, ts.K(i), ts.T(i))
}
}

View File

@@ -46,5 +46,4 @@ func TestTimestamps(t *testing.T) {
if ts.K(2) != "owl" {
t.Fatalf("third key should be owl, have %s", ts.K(2))
}
}