Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: erni27/imcache
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.9.0
Choose a base ref
...
head repository: erni27/imcache
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Apr 17, 2023

  1. Fix README (#31)

    erni27 authored Apr 17, 2023
    Copy the full SHA
    e27ff9b View commit details

Commits on Apr 20, 2023

  1. Copy the full SHA
    5030469 View commit details

Commits on Apr 22, 2023

  1. Fix typo (#34)

    This PR fixes typo in README doc.
    erni27 authored Apr 22, 2023
    Copy the full SHA
    e7deffb View commit details

Commits on Apr 23, 2023

  1. Do internal cleanup (#35)

    erni27 authored Apr 23, 2023
    Copy the full SHA
    d4da385 View commit details

Commits on Apr 30, 2023

  1. Update docs (#36)

    erni27 authored Apr 30, 2023
    Copy the full SHA
    f714bf9 View commit details
  2. Add Close method (#37)

    * Add Close method
    
    * Bump coverage
    
    * Improve godoc
    
    * Improve godoc
    
    * Improve godoc
    erni27 authored Apr 30, 2023
    Copy the full SHA
    b1f3d7b View commit details

Commits on May 2, 2023

  1. Add ReplaceKey method (#38)

    * Add ReplaceKey method
    
    * Extend unit tests
    erni27 authored May 2, 2023
    Copy the full SHA
    8231e75 View commit details

Commits on May 6, 2023

  1. Copy the full SHA
    5b7d897 View commit details
  2. Improve unit tests (#43)

    * Init default test caches
    
    * Improve unit tests
    
    * Improve ReplaceWithFunc godoc
    
    * Apply small improvements
    erni27 authored May 6, 2023
    Copy the full SHA
    b892187 View commit details

Commits on May 21, 2023

  1. Spawn a new goroutine when calling EvictionCallback (#44)

    * Spawn a new goroutine on eviction
    
    * Update docs
    
    * Extend unit tests
    
    * Do not spawn a new goroutine if not needed
    erni27 authored May 21, 2023
    Copy the full SHA
    f12f9af View commit details

Commits on Jun 15, 2023

  1. Copy the full SHA
    c557593 View commit details

Commits on Jun 27, 2023

  1. Add GetMultiple method (#48)

    * Init
    
    * Add Sharded implementation
    
    * Improve data aggregation
    erni27 authored Jun 27, 2023
    Copy the full SHA
    c4e7e46 View commit details

Commits on Jun 28, 2023

  1. Fix rand usage, typos and fields alignment (#49)

    * typos and fields alignment
    
    * typeunparen: could simplify (token) to token
    GreyXor authored Jun 28, 2023
    Copy the full SHA
    c2f6d27 View commit details

Commits on Jul 30, 2023

  1. Add CompareAndSwap method (#50)

    * Add CompareAndSwap method
    
    * Remove misleading doc
    erni27 authored Jul 30, 2023
    Copy the full SHA
    4312a64 View commit details

Commits on Dec 25, 2023

  1. Improve evictionQueue interface (#52)

    * Improve evictionQueue interface
    
    * Simplify the entry creation
    
    * Simplify enforcing eviction policy in GetAll
    
    * Refactor GetOrSet method
    erni27 authored Dec 25, 2023
    Copy the full SHA
    88192fa View commit details

Commits on Jan 13, 2024

  1. Add LFU eviction policy (#53)

    * Add LFU eviction policy
    
    * Extend unit tests
    
    * Add benchmarks
    
    * Remove redundant check
    erni27 authored Jan 13, 2024
    Copy the full SHA
    50ebc73 View commit details

Commits on Jan 14, 2024

  1. Add Random eviction policy (#55)

    erni27 authored Jan 14, 2024
    Copy the full SHA
    62fa76e View commit details

Commits on Jan 15, 2024

  1. Add Peek method (#56)

    * Add Peek method
    
    * Remove redundant var
    erni27 authored Jan 15, 2024
    Copy the full SHA
    feac194 View commit details
  2. Add PeekMultiple method (#57)

    erni27 authored Jan 15, 2024
    Copy the full SHA
    9ae8586 View commit details

Commits on Jan 16, 2024

  1. Add PeekAll method (#58)

    * Add PeekAll method
    
    * Fix comments
    erni27 authored Jan 16, 2024
    Copy the full SHA
    20ba4c2 View commit details

Commits on Jan 17, 2024

  1. Fix rand race condition in tests (#59)

    erni27 authored Jan 17, 2024
    Copy the full SHA
    803488b View commit details
  2. Update readme (#60)

    * Update README
    
    * Remove inconsistent tabs
    erni27 authored Jan 17, 2024
    Copy the full SHA
    ac0980a View commit details

Commits on Aug 29, 2024

  1. Use defer to unlock mutex (#66)

    * FIX: deadlock fix - mutex unlock via defer in GetOrSet
    
    * FIX: move all mutex Unlocks into defer
    
    * FIX: remove unnecessary new lines
    vlasashk authored Aug 29, 2024
    Copy the full SHA
    0991f9b View commit details

Commits on Dec 14, 2024

  1. Introduce fake clock in tests (#68)

    erni27 authored Dec 14, 2024
    Copy the full SHA
    bb29b58 View commit details
Showing with 5,109 additions and 3,170 deletions.
  1. +1 −1 LICENSE
  2. +194 −111 README.md
  3. +0 −680 cache.go
  4. +0 −437 cache_benchmark_test.go
  5. +0 −1,565 cache_test.go
  6. +4 −6 cleaner.go
  7. +0 −50 entry.go
  8. +0 −197 entry_test.go
  9. +358 −0 eviction.go
  10. +26 −19 expiration.go
  11. +1,234 −0 imcache.go
  12. +757 −0 imcache_benchmark_test.go
  13. +2,477 −0 imcache_test.go
  14. +0 −16 increment.go
  15. +58 −22 option.go
  16. +0 −66 queue.go
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Ernest Nguyen Hung
Copyright (c) 2024 Ernest Nguyen Hung

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
305 changes: 194 additions & 111 deletions README.md

Large diffs are not rendered by default.

680 changes: 0 additions & 680 deletions cache.go

This file was deleted.

437 changes: 0 additions & 437 deletions cache_benchmark_test.go

This file was deleted.

1,565 changes: 0 additions & 1,565 deletions cache_test.go

This file was deleted.

10 changes: 4 additions & 6 deletions cleaner.go
Original file line number Diff line number Diff line change
@@ -19,25 +19,24 @@ func newCleaner() *cleaner {
}

type cleaner struct {
mu sync.Mutex
running bool
stopCh chan struct{}
doneCh chan struct{}
mu sync.Mutex
running bool
}

func (c *cleaner) start(r eremover, interval time.Duration) error {
if interval <= 0 {
return errors.New("imcache: interval must be greater than 0")
}
c.mu.Lock()
defer c.mu.Unlock()
if c.running {
c.mu.Unlock()
return errors.New("imcache: cleaner already running")
}
c.running = true
c.stopCh = make(chan struct{})
c.doneCh = make(chan struct{})
c.mu.Unlock()
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
@@ -56,13 +55,12 @@ func (c *cleaner) start(r eremover, interval time.Duration) error {

func (c *cleaner) stop() {
c.mu.Lock()
defer c.mu.Unlock()
if !c.running {
c.mu.Unlock()
return
}
c.running = false
close(c.stopCh)
// Wait for the cleaner goroutine to stop while holding the lock.
<-c.doneCh
c.mu.Unlock()
}
50 changes: 0 additions & 50 deletions entry.go

This file was deleted.

197 changes: 0 additions & 197 deletions entry_test.go

This file was deleted.

358 changes: 358 additions & 0 deletions eviction.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
package imcache

import "math/rand"

// EvictionPolicy represents the eviction policy.
type EvictionPolicy int32

const (
// EvictionPolicyLRU is the least recently used eviction policy.
EvictionPolicyLRU EvictionPolicy = iota + 1
// EvictionPolicyLFU is the least frequently used eviction policy.
EvictionPolicyLFU
// EvictionPolicyRandom is the random eviction policy.
// It evicts the entry randomly when the max entries limit exceeded.
EvictionPolicyRandom
)

// EvictionReason is the reason why an entry was evicted.
type EvictionReason int32

@@ -20,6 +35,9 @@ const (
// limit. The least recently used entry is evicted regardless of the
// entry's expiration time.
EvictionReasonMaxEntriesExceeded
// EvictionReasonKeyReplaced indicates that the entry was evicted
// because the key was replaced.
EvictionReasonKeyReplaced
)

func (r EvictionReason) String() string {
@@ -32,6 +50,8 @@ func (r EvictionReason) String() string {
return "replaced"
case EvictionReasonMaxEntriesExceeded:
return "max entries limit exceeded"
case EvictionReasonKeyReplaced:
return "key replaced"
default:
return "unknown"
}
@@ -40,3 +60,341 @@ func (r EvictionReason) String() string {
// EvictionCallback is the callback function that is called when an entry
// is evicted.
type EvictionCallback[K comparable, V any] func(key K, val V, reason EvictionReason)

// node is the eviction queue node interface.
type node[K comparable, V any] interface {
// entry returns the imcache entry associated with the node.
entry() entry[K, V]
// setEntry sets the imcache entry associated with the node.
setEntry(entry[K, V])
}

func newEvictionQueue[K comparable, V any](limit int, policy EvictionPolicy) evictionQueue[K, V] {
if limit <= 0 {
return nopEvictionQueue[K, V]{}
}
switch policy {
case EvictionPolicyLRU:
return &lruEvictionQueue[K, V]{}
case EvictionPolicyLFU:
return &lfuEvictionQueue[K, V]{freqs: make(map[int]*lfuLruEvictionQueue[K, V])}
case EvictionPolicyRandom:
var q randomEvictionQueue[K, V] = make([]*randomNode[K, V], 0, limit)
return &q
}
return nopEvictionQueue[K, V]{}
}

// evictionQueue is the eviction queue interface.
// It is used to implement different eviction policies.
type evictionQueue[K comparable, V any] interface {
// add adds a new node to the eviction queue and returns it.
add(entry[K, V]) node[K, V]
// remove removes the node from the eviction queue.
remove(node[K, V])
// pop removes and returns the node from the eviction queue
// according to the eviction policy.
pop() node[K, V]
// touch updates the node position in the eviction queue
// according to the eviction policy.
touch(node[K, V])
// touchall updates the node positions in the eviction queue
// according to the eviction policy in the context of the
// GetAll operation.
//
// It simplifies preserving the eviction policy when the GetAll
// operation is used. Some eviction policies (e.g. LRU) may
// require to not update the node position in the eviction queue
// when the GetAll operation is used while other eviction policies
// (e.g. LFU) may require the update.
touchall()
}

//lint:ignore U1000 false positive
type lruNode[K comparable, V any] struct {
entr entry[K, V]
prev *lruNode[K, V]
next *lruNode[K, V]
}

func (n *lruNode[K, V]) entry() entry[K, V] {
return n.entr
}

func (n *lruNode[K, V]) setEntry(e entry[K, V]) {
n.entr = e
}

//lint:ignore U1000 false positive
type lruEvictionQueue[K comparable, V any] struct {
head *lruNode[K, V]
tail *lruNode[K, V]
}

func (q *lruEvictionQueue[K, V]) add(e entry[K, V]) node[K, V] {
n := &lruNode[K, V]{entr: e}
if q.head == nil {
q.tail = n
} else {
q.head.prev = n
n.next = q.head
}
q.head = n
return n
}

func (q *lruEvictionQueue[K, V]) remove(n node[K, V]) {
lrun := n.(*lruNode[K, V])
if lrun.prev == nil {
q.head = lrun.next
} else {
lrun.prev.next = lrun.next
}
if lrun.next == nil {
q.tail = lrun.prev
} else {
lrun.next.prev = lrun.prev
}
}

func (q *lruEvictionQueue[K, V]) pop() node[K, V] {
n := q.tail
q.remove(n)
return n
}

func (q *lruEvictionQueue[K, V]) touch(n node[K, V]) {
lrun := n.(*lruNode[K, V])
if lrun.prev == nil {
return
}
if lrun.next == nil {
q.tail = lrun.prev
} else {
lrun.next.prev = lrun.prev
}
lrun.prev.next = lrun.next
q.head.prev = lrun
lrun.next = q.head
lrun.prev = nil
q.head = lrun
}

func (q *lruEvictionQueue[K, V]) touchall() {}

//lint:ignore U1000 false positive
type lfuNode[K comparable, V any] struct {
entr entry[K, V]
next *lfuNode[K, V]
prev *lfuNode[K, V]
freq int
}

func (n *lfuNode[K, V]) entry() entry[K, V] {
return n.entr
}

func (n *lfuNode[K, V]) setEntry(e entry[K, V]) {
n.entr = e
}

//lint:ignore U1000 false positive
type lfuLruEvictionQueue[K comparable, V any] struct {
next *lfuLruEvictionQueue[K, V]
prev *lfuLruEvictionQueue[K, V]
head *lfuNode[K, V]
tail *lfuNode[K, V]
freq int
}

func (q *lfuLruEvictionQueue[K, V]) add(n *lfuNode[K, V]) {
if q.head == nil {
q.tail = n
} else {
q.head.prev = n
n.next = q.head
}
q.head = n
}

func (q *lfuLruEvictionQueue[K, V]) remove(n *lfuNode[K, V]) {
if n.prev == nil {
q.head = n.next
} else {
n.prev.next = n.next
}
if n.next == nil {
q.tail = n.prev
} else {
n.next.prev = n.prev
}
n.next, n.prev = nil, nil
}

func (q *lfuLruEvictionQueue[K, V]) pop() *lfuNode[K, V] {
n := q.tail
q.remove(n)
return n
}

//lint:ignore U1000 false positive
type lfuEvictionQueue[K comparable, V any] struct {
freqs map[int]*lfuLruEvictionQueue[K, V]
head *lfuLruEvictionQueue[K, V]
tail *lfuLruEvictionQueue[K, V]
}

func (q *lfuEvictionQueue[K, V]) add(e entry[K, V]) node[K, V] {
n := &lfuNode[K, V]{entr: e, freq: 1}
lruq, ok := q.freqs[1]
if !ok {
lruq = &lfuLruEvictionQueue[K, V]{freq: 1}
q.freqs[1] = lruq
if q.tail != nil {
q.tail.next = lruq
lruq.prev = q.tail
}
q.tail = lruq
if q.head == nil {
q.head = lruq
}
}
lruq.add(n)
return n
}

func (q *lfuEvictionQueue[K, V]) pop() node[K, V] {
return q.tail.pop()
}

func (q *lfuEvictionQueue[K, V]) remove(n node[K, V]) {
lfun := n.(*lfuNode[K, V])
lruq := q.freqs[lfun.freq]
lruq.remove(lfun)
if lruq.head != nil {
return
}
q.removeq(lruq)
}

func (q *lfuEvictionQueue[K, V]) removeq(lruq *lfuLruEvictionQueue[K, V]) {
if lruq.prev == nil {
q.head = lruq.next
} else {
lruq.prev.next = lruq.next
}
if lruq.next == nil {
q.tail = lruq.prev
} else {
lruq.next.prev = lruq.prev
}
delete(q.freqs, lruq.freq)
}

func (q *lfuEvictionQueue[K, V]) touch(n node[K, V]) {
lfun := n.(*lfuNode[K, V])
lruq := q.freqs[lfun.freq]
lruq.remove(lfun)
lfun.freq++
newlruq, ok := q.freqs[lfun.freq]
if !ok {
newlruq = &lfuLruEvictionQueue[K, V]{freq: lfun.freq}
q.freqs[newlruq.freq] = newlruq
newlruq.prev = lruq.prev
newlruq.next = lruq
if lruq.prev == nil {
q.head = newlruq
} else {
newlruq.prev.next = newlruq
}
lruq.prev = newlruq
}
if lruq.head == nil {
q.removeq(lruq)
}
newlruq.add(lfun)
}

func (q *lfuEvictionQueue[K, V]) touchall() {
for lruq := q.head; lruq != nil; lruq = lruq.next {
for n := lruq.head; n != nil; n = n.next {
n.freq++
}
delete(q.freqs, lruq.freq)
lruq.freq++
q.freqs[lruq.freq] = lruq
}
}

//lint:ignore U1000 false positive
type randomNode[K comparable, V any] struct {
entr entry[K, V]
idx int
}

func (n *randomNode[K, V]) entry() entry[K, V] {
return n.entr
}

func (n *randomNode[K, V]) setEntry(e entry[K, V]) {
n.entr = e
}

//lint:ignore U1000 false positive
type randomEvictionQueue[K comparable, V any] []*randomNode[K, V]

func (q *randomEvictionQueue[K, V]) add(e entry[K, V]) node[K, V] {
n := &randomNode[K, V]{entr: e}
*q = append(*q, n)
n.idx = len(*q) - 1
return n
}

func (q *randomEvictionQueue[K, V]) remove(n node[K, V]) {
randn := n.(*randomNode[K, V])
updated := *q
updated[randn.idx], updated[len(updated)-1] = updated[len(updated)-1], updated[randn.idx]
updated[randn.idx].idx = randn.idx
updated = updated[:len(updated)-1]
*q = updated
}

func (q *randomEvictionQueue[K, V]) pop() node[K, V] {
idx := rand.Intn(len(*q))
n := (*q)[idx]
q.remove(n)
return n
}

func (randomEvictionQueue[K, V]) touch(node[K, V]) {}

func (randomEvictionQueue[K, V]) touchall() {}

//lint:ignore U1000 false positive
type nopNode[K comparable, V any] entry[K, V]

func (n *nopNode[K, V]) entry() entry[K, V] {
return (entry[K, V])(*n)
}

func (n *nopNode[K, V]) setEntry(e entry[K, V]) {
*n = nopNode[K, V](e)
}

//lint:ignore U1000 false positive
type nopEvictionQueue[K comparable, V any] struct{}

func (nopEvictionQueue[K, V]) add(e entry[K, V]) node[K, V] {
return (*nopNode[K, V])(&e)
}

func (nopEvictionQueue[K, V]) remove(node[K, V]) {}

func (nopEvictionQueue[K, V]) pop() node[K, V] {
// imcache is carefully designed to never call pop on a NOP queue.
panic("imcache: pop called on a NOP eviction queue")
}

func (nopEvictionQueue[K, V]) touch(node[K, V]) {}

func (nopEvictionQueue[K, V]) touchall() {}
45 changes: 26 additions & 19 deletions expiration.go
Original file line number Diff line number Diff line change
@@ -2,10 +2,7 @@ package imcache

import "time"

const (
noExp = -1
defaultExp = 0
)
const noExp = -1

type expiration struct {
date int64
@@ -14,51 +11,61 @@ type expiration struct {

// Expiration is the expiration time of an entry.
type Expiration interface {
apply(*expiration)
new(now time.Time, defaultExp time.Duration, sliding bool) expiration
}

type expirationf func(*expiration)
type expirationf func(time.Time, time.Duration, bool) expiration

func (f expirationf) apply(e *expiration) {
f(e)
func (f expirationf) new(now time.Time, defaultExp time.Duration, sliding bool) expiration {
return f(now, defaultExp, sliding)
}

// WithExpiration returns an Expiration that sets the expiration time
// to now + d.
func WithExpiration(d time.Duration) Expiration {
return expirationf(func(e *expiration) {
e.date = time.Now().Add(d).UnixNano()
return expirationf(func(now time.Time, _ time.Duration, _ bool) expiration {
return expiration{date: now.Add(d).UnixNano()}
})
}

// WithExpirationDate returns an Expiration that sets the expiration time to t.
func WithExpirationDate(t time.Time) Expiration {
return expirationf(func(e *expiration) {
e.date = t.UnixNano()
return expirationf(func(_ time.Time, _ time.Duration, _ bool) expiration {
return expiration{date: t.UnixNano()}
})
}

// WithSlidingExpiration returns an Expiration that sets the expiration time to
// now + d and sets the sliding expiration to d.
//
// The sliding expiration is the time after which the entry is considered
// expired if it has not been accessed. If the entry has been accessed,
// the expiration time is reset to now + d where now is the time of the access.
func WithSlidingExpiration(d time.Duration) Expiration {
return expirationf(func(e *expiration) {
e.date = time.Now().Add(d).UnixNano()
e.sliding = d
return expirationf(func(now time.Time, _ time.Duration, _ bool) expiration {
return expiration{date: now.Add(d).UnixNano(), sliding: d}
})
}

// WithNoExpiration returns an Expiration that sets the expiration time
// to never expire.
func WithNoExpiration() Expiration {
return expirationf(func(e *expiration) {
e.date = noExp
return expirationf(func(_ time.Time, _ time.Duration, _ bool) expiration {
return expiration{date: noExp}
})
}

// WithDefaultExpiration returns an Expiration that sets the expiration time
// to the default expiration time.
func WithDefaultExpiration() Expiration {
return expirationf(func(e *expiration) {
e.date = defaultExp
return expirationf(func(now time.Time, defaultExp time.Duration, sliding bool) expiration {
if defaultExp == noExp {
return expiration{date: noExp}
}
var slidingExp time.Duration
if sliding {
slidingExp = defaultExp
}
return expiration{date: now.Add(defaultExp).UnixNano(), sliding: slidingExp}
})
}
1,234 changes: 1,234 additions & 0 deletions imcache.go

Large diffs are not rendered by default.

757 changes: 757 additions & 0 deletions imcache_benchmark_test.go

Large diffs are not rendered by default.

2,477 changes: 2,477 additions & 0 deletions imcache_test.go

Large diffs are not rendered by default.

16 changes: 0 additions & 16 deletions increment.go

This file was deleted.

80 changes: 58 additions & 22 deletions option.go
Original file line number Diff line number Diff line change
@@ -2,61 +2,97 @@ package imcache

import "time"

// Option is a Cache option.
// options holds the cache configuration.
type options[K comparable, V any] struct {
onEviction EvictionCallback[K, V]
defaultExp time.Duration
sliding bool
maxEntriesLimit int
evictionPolicy EvictionPolicy
cleanerInterval time.Duration
}

// Option configures the cache.
type Option[K comparable, V any] interface {
apply(*Cache[K, V])
apply(*options[K, V])
}

type optionf[K comparable, V any] func(*Cache[K, V])
type optionf[K comparable, V any] func(*options[K, V])

//lint:ignore U1000 false positive
func (f optionf[K, V]) apply(c *Cache[K, V]) {
f(c)
func (f optionf[K, V]) apply(o *options[K, V]) {
f(o)
}

// WithEvictionCallbackOption returns an Option that sets the Cache
// WithEvictionCallbackOption returns an Option that sets the cache
// eviction callback.
func WithEvictionCallbackOption[K comparable, V any](f EvictionCallback[K, V]) Option[K, V] {
return optionf[K, V](func(c *Cache[K, V]) {
c.onEviction = f
return optionf[K, V](func(o *options[K, V]) {
o.onEviction = f
})
}

// WithDefaultExpirationOption returns an Option that sets the Cache
// WithDefaultExpirationOption returns an Option that sets the cache
// default expiration.
func WithDefaultExpirationOption[K comparable, V any](d time.Duration) Option[K, V] {
return optionf[K, V](func(c *Cache[K, V]) {
return optionf[K, V](func(o *options[K, V]) {
if d <= 0 {
return
}
c.defaultExp = d
o.defaultExp = d
})
}

// WithDefaultSlidingExpirationOption returns an Option that sets the Cache
// WithDefaultSlidingExpirationOption returns an Option that sets the cache
// default sliding expiration.
func WithDefaultSlidingExpirationOption[K comparable, V any](d time.Duration) Option[K, V] {
return optionf[K, V](func(c *Cache[K, V]) {
return optionf[K, V](func(o *options[K, V]) {
if d <= 0 {
return
}
c.defaultExp = d
c.sliding = true
o.defaultExp = d
o.sliding = true
})
}

// WithMaxEntriesOption returns an Option that sets the Cache maximum number
// of entries. When the maximum number of entries is exceeded, the least
// recently used entry is evicted regardless of the entry's expiration time.
// WithMaxEntriesLimitOption returns an Option that sets the cache maximum
// number of entries. When the limit is exceeded, the entry is evicted
// according to the eviction policy.
//
// If used with Sharded type, the maximum size is per shard,
// not the total size of all shards.
func WithMaxEntriesLimitOption[K comparable, V any](limit int, policy EvictionPolicy) Option[K, V] {
return optionf[K, V](func(o *options[K, V]) {
o.maxEntriesLimit = limit
o.evictionPolicy = policy
})
}

// WithMaxEntriesOption returns an Option that sets the cache maximum number
// of entries. When the maximum number of entries is exceeded, the entry is evicted
// according to the LRU eviction policy.
//
// If used with Sharded type, the maximum size is per shard,
// not the total size of all shards.
//
// Deprecated: Use WithMaxEntriesLimitOption instead.
func WithMaxEntriesOption[K comparable, V any](n int) Option[K, V] {
return optionf[K, V](func(c *Cache[K, V]) {
if n <= 0 {
return WithMaxEntriesLimitOption[K, V](n, EvictionPolicyLRU)
}

// WithCleanerOption returns an Option that sets a cache cleaner that
// periodically removes expired entries from the cache.
//
// A cleaner runs in a separate goroutine. It removes expired entries
// every interval. If the interval is less than or equal to zero,
// the cleaner is disabled.
//
// A cleaner is stopped when the cache is closed.
func WithCleanerOption[K comparable, V any](interval time.Duration) Option[K, V] {
return optionf[K, V](func(o *options[K, V]) {
if interval <= 0 {
return
}
c.size = n
c.queue = &fifoq[K]{}
o.cleanerInterval = interval
})
}
66 changes: 0 additions & 66 deletions queue.go

This file was deleted.