Skip to content

Commit

Permalink
Merge pull request #3 from twharmon/evict
Browse files Browse the repository at this point in the history
Re-write eviction policy logic
  • Loading branch information
twharmon authored Apr 11, 2022
2 parents a764ab1 + 8e7ed1f commit bb98c05
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 45 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func main() {
// Create a basic config.
cfg := gocache.NewConfig().
WithMaxCapacity(1000).
WithDefaultTTL(time.Second, cocache.NewTTLMode().UpdateOnGet())
WithDefaultEvictionPolicy(time.Second, cocache.NewEvictionPolicy().UpdateOnGet())

// Create a cache with that config.
cache := gocache.New[string, int](cfg)
Expand Down
56 changes: 29 additions & 27 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
"time"
)

type TTLMode byte
type EvictionPolicy byte

type Config struct {
capacityHint int
defaultTTL time.Duration
maxCapacity int
ttlMode TTLMode
capacityHint int
defaultEvictionTtl time.Duration
maxCapacity int
evictionPolicy EvictionPolicy
}

// NewConfig creates a new config with default settings.
Expand All @@ -28,10 +28,10 @@ func (c *Config) WithCapacityHint(size int) *Config {
return c
}

// WithDefaultTTL sets the default TTL settings.
func (c *Config) WithDefaultTTL(ttl time.Duration, mode *TTLMode) *Config {
c.defaultTTL = ttl
c.ttlMode = *mode
// WithDefaultEvictionPolicy sets the default eviction policy.
func (c *Config) WithDefaultEvictionPolicy(ttl time.Duration, mode *EvictionPolicy) *Config {
c.defaultEvictionTtl = ttl
c.evictionPolicy = *mode
return c
}

Expand All @@ -45,34 +45,36 @@ func (c *Config) WithMaxCapacity(size int) *Config {
}

const (
ttlModeSetMask = 0b00000001
ttlModeGetMask = 0b00000010
ttlModeHasMask = 0b00000100
ttlModeActivePruningMask = 0b10000000
evictionPolicySetMask = 0b00000001
evictionPolicyGetMask = 0b00000010
evictionPolicyHasMask = 0b00000100
evictionPolicyActivePruningMask = 0b10000000
)

// NewTTLMode creates a new TTL mode. By default, TTL is not affected
// when Get or Has is called.
func NewTTLMode() *TTLMode {
mode := TTLMode(ttlModeSetMask)
// NewEvictionPolicy creates a new EvictionPolicy. By default, TTL is
// not affected when Get or Has is called.
func NewEvictionPolicy() *EvictionPolicy {
mode := EvictionPolicy(evictionPolicySetMask)
return &mode
}

// UpdateOnGet sets the mode to update TTL when Get is called.
func (m *TTLMode) UpdateOnGet() *TTLMode {
*m |= ttlModeGetMask
// UpdateOnGet sets the eviction policy to update TTL when Get is
// called.
func (m *EvictionPolicy) UpdateOnGet() *EvictionPolicy {
*m |= evictionPolicyGetMask
return m
}

// UpdateOnHas sets the mode to update TTL when Has is called.
func (m *TTLMode) UpdateOnHas() *TTLMode {
*m |= ttlModeHasMask
// UpdateOnHas sets the eviction policy to update TTL when Has is
// called.
func (m *EvictionPolicy) UpdateOnHas() *EvictionPolicy {
*m |= evictionPolicyHasMask
return m
}

// ActivePruning sets the mode to regularly scan the cache to expire
// old items.
func (m *TTLMode) ActivePruning() *TTLMode {
*m |= ttlModeActivePruningMask
// ActivePruning sets the eviction policy to regularly scan the cache
// to expire old items.
func (m *EvictionPolicy) ActivePruning() *EvictionPolicy {
*m |= evictionPolicyActivePruningMask
return m
}
22 changes: 9 additions & 13 deletions gocache.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import (

var never = time.Now().Add(time.Hour * 24 * 365 * 100)

type Key interface {
int | uint | int8 | uint8 | int16 | uint16 | int32 | uint32 | int64 | uint64 | string
}

type Cache[K Key, V any] struct {
type Cache[K comparable, V any] struct {
store map[K]*entry[V]
mu sync.Mutex
config *Config
Expand All @@ -23,7 +19,7 @@ type entry[V any] struct {
exp bool
}

func New[K Key, V any](config ...*Config) *Cache[K, V] {
func New[K comparable, V any](config ...*Config) *Cache[K, V] {
c := &Cache[K, V]{}
if len(config) > 0 {
c.config = config[0]
Expand All @@ -36,7 +32,7 @@ func New[K Key, V any](config ...*Config) *Cache[K, V] {
}

func (c *Cache[K, V]) watch() {
if c.config.ttlMode&ttlModeActivePruningMask == 0 {
if c.config.evictionPolicy&evictionPolicyActivePruningMask == 0 {
return
}
for {
Expand Down Expand Up @@ -91,8 +87,8 @@ func (c *Cache[K, V]) Set(key K, val V, ttl ...time.Duration) {
if len(ttl) > 0 {
e.ts = e.ts.Add(ttl[0])
e.exp = true
} else if c.config.ttlMode&ttlModeSetMask > 0 {
e.ts = e.ts.Add(c.config.defaultTTL)
} else if c.config.evictionPolicy&evictionPolicySetMask > 0 {
e.ts = e.ts.Add(c.config.defaultEvictionTtl)
e.exp = true
}
c.mu.Lock()
Expand All @@ -109,8 +105,8 @@ func (c *Cache[K, V]) Get(key K) V {
var v V
return v
}
if c.config.ttlMode&ttlModeGetMask > 0 {
e.ts = time.Now().Add(c.config.defaultTTL)
if c.config.evictionPolicy&evictionPolicyGetMask > 0 {
e.ts = time.Now().Add(c.config.defaultEvictionTtl)
}
return e.val
}
Expand All @@ -126,8 +122,8 @@ func (c *Cache[K, V]) Has(key K) bool {
c.expireUnsafe()
return false
}
if c.config.ttlMode&ttlModeHasMask > 0 {
e.ts = time.Now().Add(c.config.defaultTTL)
if c.config.evictionPolicy&evictionPolicyHasMask > 0 {
e.ts = time.Now().Add(c.config.defaultEvictionTtl)
}
return true
}
Expand Down
8 changes: 4 additions & 4 deletions gocache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func TestConfigCapacityHint(t *testing.T) {
}

func TestConfigTTLHasHit(t *testing.T) {
db := gocache.New[string, int](gocache.NewConfig().WithDefaultTTL(time.Second, gocache.NewTTLMode()))
db := gocache.New[string, int](gocache.NewConfig().WithDefaultEvictionPolicy(time.Second, gocache.NewEvictionPolicy()))
want := true
db.Set("foo", 5)
got := db.Has("foo")
Expand All @@ -117,7 +117,7 @@ func TestConfigTTLHasHit(t *testing.T) {
}

func TestConfigTTLHasExp(t *testing.T) {
db := gocache.New[string, int](gocache.NewConfig().WithDefaultTTL(time.Nanosecond, gocache.NewTTLMode()))
db := gocache.New[string, int](gocache.NewConfig().WithDefaultEvictionPolicy(time.Nanosecond, gocache.NewEvictionPolicy()))
want := false
db.Set("foo", 5)
time.Sleep(time.Microsecond)
Expand All @@ -128,7 +128,7 @@ func TestConfigTTLHasExp(t *testing.T) {
}

func TestConfigTTLGetExp(t *testing.T) {
db := gocache.New[string, int](gocache.NewConfig().WithDefaultTTL(time.Nanosecond, gocache.NewTTLMode()))
db := gocache.New[string, int](gocache.NewConfig().WithDefaultEvictionPolicy(time.Nanosecond, gocache.NewEvictionPolicy()))
want := 0
db.Set("foo", 5)
time.Sleep(time.Microsecond)
Expand All @@ -139,7 +139,7 @@ func TestConfigTTLGetExp(t *testing.T) {
}

func TestConfigTTLGetHit(t *testing.T) {
db := gocache.New[string, int](gocache.NewConfig().WithDefaultTTL(time.Second, gocache.NewTTLMode()))
db := gocache.New[string, int](gocache.NewConfig().WithDefaultEvictionPolicy(time.Second, gocache.NewEvictionPolicy()))
want := 5
db.Set("foo", want)
got := db.Get("foo")
Expand Down

0 comments on commit bb98c05

Please sign in to comment.