Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/NOTICE
diff options
context:
space:
mode:
authorGitLab Renovate Bot <gitlab-bot@gitlab.com>2022-11-23 22:24:10 +0300
committerKarthik Nayak <knayak@gitlab.com>2022-11-24 17:18:41 +0300
commitdd5a9e74e88547c277f6fba9252f4867af946be0 (patch)
tree5e441b00c0fad243d1dec14ee291d6dc7a5ef28f /NOTICE
parent2f191c3e0dd2edf836ac34c4980c5202d6e68846 (diff)
go: Update module github.com/hashicorp/golang-lru to v2
Diffstat (limited to 'NOTICE')
-rw-r--r--NOTICE579
1 files changed, 370 insertions, 209 deletions
diff --git a/NOTICE b/NOTICE
index 84abc2c04..2b3f3d001 100644
--- a/NOTICE
+++ b/NOTICE
@@ -10135,7 +10135,7 @@ func BenchmarkGenerateUUIDWithReader(b *testing.B) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-ci.yml - github.com/hashicorp/golang-lru/.github/workflows
+ci.yml - github.com/hashicorp/golang-lru/v2/.github/workflows
name: build
on:
@@ -10170,7 +10170,7 @@ jobs:
run: $GITHUB_WORKSPACE/golangci-lint run --out-format=github-actions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.gitignore - github.com/hashicorp/golang-lru
+.gitignore - github.com/hashicorp/golang-lru/v2
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
@@ -10196,7 +10196,7 @@ _testmain.go
*.test
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.golangci.yml - github.com/hashicorp/golang-lru
+.golangci.yml - github.com/hashicorp/golang-lru/v2
linters:
enable:
- megacheck
@@ -10229,14 +10229,14 @@ issues:
exclude-use-default: false
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-2q.go - github.com/hashicorp/golang-lru
+2q.go - github.com/hashicorp/golang-lru/v2
package lru
import (
"fmt"
"sync"
- "github.com/hashicorp/golang-lru/simplelru"
+ "github.com/hashicorp/golang-lru/v2/simplelru"
)
const (
@@ -10258,25 +10258,25 @@ const (
// computationally about 2x the cost, and adds some metadata over
// head. The ARCCache is similar, but does not require setting any
// parameters.
-type TwoQueueCache struct {
+type TwoQueueCache[K comparable, V any] struct {
size int
recentSize int
- recent simplelru.LRUCache
- frequent simplelru.LRUCache
- recentEvict simplelru.LRUCache
+ recent simplelru.LRUCache[K, V]
+ frequent simplelru.LRUCache[K, V]
+ recentEvict simplelru.LRUCache[K, V]
lock sync.RWMutex
}
// New2Q creates a new TwoQueueCache using the default
// values for the parameters.
-func New2Q(size int) (*TwoQueueCache, error) {
- return New2QParams(size, Default2QRecentRatio, Default2QGhostEntries)
+func New2Q[K comparable, V any](size int) (*TwoQueueCache[K, V], error) {
+ return New2QParams[K, V](size, Default2QRecentRatio, Default2QGhostEntries)
}
// New2QParams creates a new TwoQueueCache using the provided
// parameter values.
-func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, error) {
+func New2QParams[K comparable, V any](size int, recentRatio, ghostRatio float64) (*TwoQueueCache[K, V], error) {
if size <= 0 {
return nil, fmt.Errorf("invalid size")
}
@@ -10292,21 +10292,21 @@ func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, err
evictSize := int(float64(size) * ghostRatio)
// Allocate the LRUs
- recent, err := simplelru.NewLRU(size, nil)
+ recent, err := simplelru.NewLRU[K, V](size, nil)
if err != nil {
return nil, err
}
- frequent, err := simplelru.NewLRU(size, nil)
+ frequent, err := simplelru.NewLRU[K, V](size, nil)
if err != nil {
return nil, err
}
- recentEvict, err := simplelru.NewLRU(evictSize, nil)
+ recentEvict, err := simplelru.NewLRU[K, V](evictSize, nil)
if err != nil {
return nil, err
}
// Initialize the cache
- c := &TwoQueueCache{
+ c := &TwoQueueCache[K, V]{
size: size,
recentSize: recentSize,
recent: recent,
@@ -10317,7 +10317,7 @@ func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, err
}
// Get looks up a key's value from the cache.
-func (c *TwoQueueCache) Get(key interface{}) (value interface{}, ok bool) {
+func (c *TwoQueueCache[K, V]) Get(key K) (value V, ok bool) {
c.lock.Lock()
defer c.lock.Unlock()
@@ -10335,11 +10335,11 @@ func (c *TwoQueueCache) Get(key interface{}) (value interface{}, ok bool) {
}
// No hit
- return nil, false
+ return
}
// Add adds a value to the cache.
-func (c *TwoQueueCache) Add(key, value interface{}) {
+func (c *TwoQueueCache[K, V]) Add(key K, value V) {
c.lock.Lock()
defer c.lock.Unlock()
@@ -10373,7 +10373,7 @@ func (c *TwoQueueCache) Add(key, value interface{}) {
}
// ensureSpace is used to ensure we have space in the cache
-func (c *TwoQueueCache) ensureSpace(recentEvict bool) {
+func (c *TwoQueueCache[K, V]) ensureSpace(recentEvict bool) {
// If we have space, nothing to do
recentLen := c.recent.Len()
freqLen := c.frequent.Len()
@@ -10385,7 +10385,8 @@ func (c *TwoQueueCache) ensureSpace(recentEvict bool) {
// the target, evict from there
if recentLen > 0 && (recentLen > c.recentSize || (recentLen == c.recentSize && !recentEvict)) {
k, _, _ := c.recent.RemoveOldest()
- c.recentEvict.Add(k, nil)
+ var empty V
+ c.recentEvict.Add(k, empty)
return
}
@@ -10394,7 +10395,7 @@ func (c *TwoQueueCache) ensureSpace(recentEvict bool) {
}
// Len returns the number of items in the cache.
-func (c *TwoQueueCache) Len() int {
+func (c *TwoQueueCache[K, V]) Len() int {
c.lock.RLock()
defer c.lock.RUnlock()
return c.recent.Len() + c.frequent.Len()
@@ -10402,7 +10403,7 @@ func (c *TwoQueueCache) Len() int {
// Keys returns a slice of the keys in the cache.
// The frequently used keys are first in the returned slice.
-func (c *TwoQueueCache) Keys() []interface{} {
+func (c *TwoQueueCache[K, V]) Keys() []K {
c.lock.RLock()
defer c.lock.RUnlock()
k1 := c.frequent.Keys()
@@ -10411,7 +10412,7 @@ func (c *TwoQueueCache) Keys() []interface{} {
}
// Remove removes the provided key from the cache.
-func (c *TwoQueueCache) Remove(key interface{}) {
+func (c *TwoQueueCache[K, V]) Remove(key K) {
c.lock.Lock()
defer c.lock.Unlock()
if c.frequent.Remove(key) {
@@ -10426,7 +10427,7 @@ func (c *TwoQueueCache) Remove(key interface{}) {
}
// Purge is used to completely clear the cache.
-func (c *TwoQueueCache) Purge() {
+func (c *TwoQueueCache[K, V]) Purge() {
c.lock.Lock()
defer c.lock.Unlock()
c.recent.Purge()
@@ -10436,7 +10437,7 @@ func (c *TwoQueueCache) Purge() {
// Contains is used to check if the cache contains a key
// without updating recency or frequency.
-func (c *TwoQueueCache) Contains(key interface{}) bool {
+func (c *TwoQueueCache[K, V]) Contains(key K) bool {
c.lock.RLock()
defer c.lock.RUnlock()
return c.frequent.Contains(key) || c.recent.Contains(key)
@@ -10444,7 +10445,7 @@ func (c *TwoQueueCache) Contains(key interface{}) bool {
// Peek is used to inspect the cache value of a key
// without updating recency or frequency.
-func (c *TwoQueueCache) Peek(key interface{}) (value interface{}, ok bool) {
+func (c *TwoQueueCache[K, V]) Peek(key K) (value V, ok bool) {
c.lock.RLock()
defer c.lock.RUnlock()
if val, ok := c.frequent.Peek(key); ok {
@@ -10454,7 +10455,7 @@ func (c *TwoQueueCache) Peek(key interface{}) (value interface{}, ok bool) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-2q_test.go - github.com/hashicorp/golang-lru
+2q_test.go - github.com/hashicorp/golang-lru/v2
package lru
import (
@@ -10462,7 +10463,7 @@ import (
)
func Benchmark2Q_Rand(b *testing.B) {
- l, err := New2Q(8192)
+ l, err := New2Q[int64, int64](8192)
if err != nil {
b.Fatalf("err: %v", err)
}
@@ -10491,7 +10492,7 @@ func Benchmark2Q_Rand(b *testing.B) {
}
func Benchmark2Q_Freq(b *testing.B) {
- l, err := New2Q(8192)
+ l, err := New2Q[int64, int64](8192)
if err != nil {
b.Fatalf("err: %v", err)
}
@@ -10524,7 +10525,7 @@ func Benchmark2Q_Freq(b *testing.B) {
func Test2Q_RandomOps(t *testing.T) {
size := 128
- l, err := New2Q(128)
+ l, err := New2Q[int64, int64](128)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -10550,7 +10551,7 @@ func Test2Q_RandomOps(t *testing.T) {
}
func Test2Q_Get_RecentToFrequent(t *testing.T) {
- l, err := New2Q(128)
+ l, err := New2Q[int, int](128)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -10596,7 +10597,7 @@ func Test2Q_Get_RecentToFrequent(t *testing.T) {
}
func Test2Q_Add_RecentToFrequent(t *testing.T) {
- l, err := New2Q(128)
+ l, err := New2Q[int, int](128)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -10630,7 +10631,7 @@ func Test2Q_Add_RecentToFrequent(t *testing.T) {
}
func Test2Q_Add_RecentEvict(t *testing.T) {
- l, err := New2Q(4)
+ l, err := New2Q[int, int](4)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -10677,7 +10678,7 @@ func Test2Q_Add_RecentEvict(t *testing.T) {
}
func Test2Q(t *testing.T) {
- l, err := New2Q(128)
+ l, err := New2Q[int, int](128)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -10725,7 +10726,7 @@ func Test2Q(t *testing.T) {
// Test that Contains doesn't update recent-ness
func Test2Q_Contains(t *testing.T) {
- l, err := New2Q(2)
+ l, err := New2Q[int, int](2)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -10744,7 +10745,7 @@ func Test2Q_Contains(t *testing.T) {
// Test that Peek doesn't update recent-ness
func Test2Q_Peek(t *testing.T) {
- l, err := New2Q(2)
+ l, err := New2Q[int, int](2)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -10762,7 +10763,7 @@ func Test2Q_Peek(t *testing.T) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LICENSE - github.com/hashicorp/golang-lru
+LICENSE - github.com/hashicorp/golang-lru/v2
Copyright (c) 2014 HashiCorp, Inc.
Mozilla Public License, version 2.0
@@ -11129,7 +11130,7 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice
the Mozilla Public License, v. 2.0.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-README.md - github.com/hashicorp/golang-lru
+README.md - github.com/hashicorp/golang-lru/v2
golang-lru
==========
@@ -11139,7 +11140,7 @@ thread safe LRU cache. It is based on the cache in Groupcache.
Documentation
=============
-Full docs are available on [Godoc](https://pkg.go.dev/github.com/hashicorp/golang-lru)
+Full docs are available on [Go Packages](https://pkg.go.dev/github.com/hashicorp/golang-lru/v2)
Example
=======
@@ -11157,13 +11158,13 @@ if l.Len() != 128 {
```
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-arc.go - github.com/hashicorp/golang-lru
+arc.go - github.com/hashicorp/golang-lru/v2
package lru
import (
"sync"
- "github.com/hashicorp/golang-lru/simplelru"
+ "github.com/hashicorp/golang-lru/v2/simplelru"
)
// ARCCache is a thread-safe fixed size Adaptive Replacement Cache (ARC).
@@ -11174,41 +11175,41 @@ import (
// it is roughly 2x the cost, and the extra memory overhead is linear
// with the size of the cache. ARC has been patented by IBM, but is
// similar to the TwoQueueCache (2Q) which requires setting parameters.
-type ARCCache struct {
+type ARCCache[K comparable, V any] struct {
size int // Size is the total capacity of the cache
p int // P is the dynamic preference towards T1 or T2
- t1 simplelru.LRUCache // T1 is the LRU for recently accessed items
- b1 simplelru.LRUCache // B1 is the LRU for evictions from t1
+ t1 simplelru.LRUCache[K, V] // T1 is the LRU for recently accessed items
+ b1 simplelru.LRUCache[K, V] // B1 is the LRU for evictions from t1
- t2 simplelru.LRUCache // T2 is the LRU for frequently accessed items
- b2 simplelru.LRUCache // B2 is the LRU for evictions from t2
+ t2 simplelru.LRUCache[K, V] // T2 is the LRU for frequently accessed items
+ b2 simplelru.LRUCache[K, V] // B2 is the LRU for evictions from t2
lock sync.RWMutex
}
// NewARC creates an ARC of the given size
-func NewARC(size int) (*ARCCache, error) {
+func NewARC[K comparable, V any](size int) (*ARCCache[K, V], error) {
// Create the sub LRUs
- b1, err := simplelru.NewLRU(size, nil)
+ b1, err := simplelru.NewLRU[K, V](size, nil)
if err != nil {
return nil, err
}
- b2, err := simplelru.NewLRU(size, nil)
+ b2, err := simplelru.NewLRU[K, V](size, nil)
if err != nil {
return nil, err
}
- t1, err := simplelru.NewLRU(size, nil)
+ t1, err := simplelru.NewLRU[K, V](size, nil)
if err != nil {
return nil, err
}
- t2, err := simplelru.NewLRU(size, nil)
+ t2, err := simplelru.NewLRU[K, V](size, nil)
if err != nil {
return nil, err
}
// Initialize the ARC
- c := &ARCCache{
+ c := &ARCCache[K, V]{
size: size,
p: 0,
t1: t1,
@@ -11220,7 +11221,7 @@ func NewARC(size int) (*ARCCache, error) {
}
// Get looks up a key's value from the cache.
-func (c *ARCCache) Get(key interface{}) (value interface{}, ok bool) {
+func (c *ARCCache[K, V]) Get(key K) (value V, ok bool) {
c.lock.Lock()
defer c.lock.Unlock()
@@ -11238,11 +11239,11 @@ func (c *ARCCache) Get(key interface{}) (value interface{}, ok bool) {
}
// No hit
- return nil, false
+ return
}
// Add adds a value to the cache.
-func (c *ARCCache) Add(key, value interface{}) {
+func (c *ARCCache[K, V]) Add(key K, value V) {
c.lock.Lock()
defer c.lock.Unlock()
@@ -11337,30 +11338,32 @@ func (c *ARCCache) Add(key, value interface{}) {
// replace is used to adaptively evict from either T1 or T2
// based on the current learned value of P
-func (c *ARCCache) replace(b2ContainsKey bool) {
+func (c *ARCCache[K, V]) replace(b2ContainsKey bool) {
t1Len := c.t1.Len()
if t1Len > 0 && (t1Len > c.p || (t1Len == c.p && b2ContainsKey)) {
k, _, ok := c.t1.RemoveOldest()
if ok {
- c.b1.Add(k, nil)
+ var empty V
+ c.b1.Add(k, empty)
}
} else {
k, _, ok := c.t2.RemoveOldest()
if ok {
- c.b2.Add(k, nil)
+ var empty V
+ c.b2.Add(k, empty)
}
}
}
// Len returns the number of cached entries
-func (c *ARCCache) Len() int {
+func (c *ARCCache[K, V]) Len() int {
c.lock.RLock()
defer c.lock.RUnlock()
return c.t1.Len() + c.t2.Len()
}
// Keys returns all the cached keys
-func (c *ARCCache) Keys() []interface{} {
+func (c *ARCCache[K, V]) Keys() []K {
c.lock.RLock()
defer c.lock.RUnlock()
k1 := c.t1.Keys()
@@ -11369,7 +11372,7 @@ func (c *ARCCache) Keys() []interface{} {
}
// Remove is used to purge a key from the cache
-func (c *ARCCache) Remove(key interface{}) {
+func (c *ARCCache[K, V]) Remove(key K) {
c.lock.Lock()
defer c.lock.Unlock()
if c.t1.Remove(key) {
@@ -11387,7 +11390,7 @@ func (c *ARCCache) Remove(key interface{}) {
}
// Purge is used to clear the cache
-func (c *ARCCache) Purge() {
+func (c *ARCCache[K, V]) Purge() {
c.lock.Lock()
defer c.lock.Unlock()
c.t1.Purge()
@@ -11398,7 +11401,7 @@ func (c *ARCCache) Purge() {
// Contains is used to check if the cache contains a key
// without updating recency or frequency.
-func (c *ARCCache) Contains(key interface{}) bool {
+func (c *ARCCache[K, V]) Contains(key K) bool {
c.lock.RLock()
defer c.lock.RUnlock()
return c.t1.Contains(key) || c.t2.Contains(key)
@@ -11406,7 +11409,7 @@ func (c *ARCCache) Contains(key interface{}) bool {
// Peek is used to inspect the cache value of a key
// without updating recency or frequency.
-func (c *ARCCache) Peek(key interface{}) (value interface{}, ok bool) {
+func (c *ARCCache[K, V]) Peek(key K) (value V, ok bool) {
c.lock.RLock()
defer c.lock.RUnlock()
if val, ok := c.t1.Peek(key); ok {
@@ -11416,7 +11419,7 @@ func (c *ARCCache) Peek(key interface{}) (value interface{}, ok bool) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-arc_test.go - github.com/hashicorp/golang-lru
+arc_test.go - github.com/hashicorp/golang-lru/v2
package lru
import (
@@ -11430,7 +11433,7 @@ func init() {
}
func BenchmarkARC_Rand(b *testing.B) {
- l, err := NewARC(8192)
+ l, err := NewARC[int64, int64](8192)
if err != nil {
b.Fatalf("err: %v", err)
}
@@ -11459,7 +11462,7 @@ func BenchmarkARC_Rand(b *testing.B) {
}
func BenchmarkARC_Freq(b *testing.B) {
- l, err := NewARC(8192)
+ l, err := NewARC[int64, int64](8192)
if err != nil {
b.Fatalf("err: %v", err)
}
@@ -11492,7 +11495,7 @@ func BenchmarkARC_Freq(b *testing.B) {
func TestARC_RandomOps(t *testing.T) {
size := 128
- l, err := NewARC(128)
+ l, err := NewARC[int64, int64](128)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -11522,7 +11525,7 @@ func TestARC_RandomOps(t *testing.T) {
}
func TestARC_Get_RecentToFrequent(t *testing.T) {
- l, err := NewARC(128)
+ l, err := NewARC[int, int](128)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -11568,7 +11571,7 @@ func TestARC_Get_RecentToFrequent(t *testing.T) {
}
func TestARC_Add_RecentToFrequent(t *testing.T) {
- l, err := NewARC(128)
+ l, err := NewARC[int, int](128)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -11602,7 +11605,7 @@ func TestARC_Add_RecentToFrequent(t *testing.T) {
}
func TestARC_Adaptive(t *testing.T) {
- l, err := NewARC(4)
+ l, err := NewARC[int, int](4)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -11711,7 +11714,7 @@ func TestARC_Adaptive(t *testing.T) {
}
func TestARC(t *testing.T) {
- l, err := NewARC(128)
+ l, err := NewARC[int, int](128)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -11759,7 +11762,7 @@ func TestARC(t *testing.T) {
// Test that Contains doesn't update recent-ness
func TestARC_Contains(t *testing.T) {
- l, err := NewARC(2)
+ l, err := NewARC[int, int](2)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -11778,7 +11781,7 @@ func TestARC_Contains(t *testing.T) {
// Test that Peek doesn't update recent-ness
func TestARC_Peek(t *testing.T) {
- l, err := NewARC(2)
+ l, err := NewARC[int, int](2)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -11796,7 +11799,7 @@ func TestARC_Peek(t *testing.T) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-doc.go - github.com/hashicorp/golang-lru
+doc.go - github.com/hashicorp/golang-lru/v2
// Package lru provides three different LRU caches of varying sophistication.
//
// Cache is a simple LRU cache. It is based on the
@@ -11820,19 +11823,19 @@ doc.go - github.com/hashicorp/golang-lru
package lru
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-go.mod - github.com/hashicorp/golang-lru
-module github.com/hashicorp/golang-lru
+go.mod - github.com/hashicorp/golang-lru/v2
+module github.com/hashicorp/golang-lru/v2
-go 1.12
+go 1.18
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-lru.go - github.com/hashicorp/golang-lru
+lru.go - github.com/hashicorp/golang-lru/v2
package lru
import (
"sync"
- "github.com/hashicorp/golang-lru/simplelru"
+ "github.com/hashicorp/golang-lru/v2/simplelru"
)
const (
@@ -11841,23 +11844,24 @@ const (
)
// Cache is a thread-safe fixed size LRU cache.
-type Cache struct {
- lru *simplelru.LRU
- evictedKeys, evictedVals []interface{}
- onEvictedCB func(k, v interface{})
- lock sync.RWMutex
+type Cache[K comparable, V any] struct {
+ lru *simplelru.LRU[K, V]
+ evictedKeys []K
+ evictedVals []V
+ onEvictedCB func(k K, v V)
+ lock sync.RWMutex
}
// New creates an LRU of the given size.
-func New(size int) (*Cache, error) {
- return NewWithEvict(size, nil)
+func New[K comparable, V any](size int) (*Cache[K, V], error) {
+ return NewWithEvict[K, V](size, nil)
}
// NewWithEvict constructs a fixed size cache with the given eviction
// callback.
-func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, err error) {
+func NewWithEvict[K comparable, V any](size int, onEvicted func(key K, value V)) (c *Cache[K, V], err error) {
// create a cache with default settings
- c = &Cache{
+ c = &Cache[K, V]{
onEvictedCB: onEvicted,
}
if onEvicted != nil {
@@ -11868,21 +11872,22 @@ func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, e
return
}
-func (c *Cache) initEvictBuffers() {
- c.evictedKeys = make([]interface{}, 0, DefaultEvictedBufferSize)
- c.evictedVals = make([]interface{}, 0, DefaultEvictedBufferSize)
+func (c *Cache[K, V]) initEvictBuffers() {
+ c.evictedKeys = make([]K, 0, DefaultEvictedBufferSize)
+ c.evictedVals = make([]V, 0, DefaultEvictedBufferSize)
}
// onEvicted save evicted key/val and sent in externally registered callback
// outside of critical section
-func (c *Cache) onEvicted(k, v interface{}) {
+func (c *Cache[K, V]) onEvicted(k K, v V) {
c.evictedKeys = append(c.evictedKeys, k)
c.evictedVals = append(c.evictedVals, v)
}
// Purge is used to completely clear the cache.
-func (c *Cache) Purge() {
- var ks, vs []interface{}
+func (c *Cache[K, V]) Purge() {
+ var ks []K
+ var vs []V
c.lock.Lock()
c.lru.Purge()
if c.onEvictedCB != nil && len(c.evictedKeys) > 0 {
@@ -11899,8 +11904,9 @@ func (c *Cache) Purge() {
}
// Add adds a value to the cache. Returns true if an eviction occurred.
-func (c *Cache) Add(key, value interface{}) (evicted bool) {
- var k, v interface{}
+func (c *Cache[K, V]) Add(key K, value V) (evicted bool) {
+ var k K
+ var v V
c.lock.Lock()
evicted = c.lru.Add(key, value)
if c.onEvictedCB != nil && evicted {
@@ -11915,7 +11921,7 @@ func (c *Cache) Add(key, value interface{}) (evicted bool) {
}
// Get looks up a key's value from the cache.
-func (c *Cache) Get(key interface{}) (value interface{}, ok bool) {
+func (c *Cache[K, V]) Get(key K) (value V, ok bool) {
c.lock.Lock()
value, ok = c.lru.Get(key)
c.lock.Unlock()
@@ -11924,7 +11930,7 @@ func (c *Cache) Get(key interface{}) (value interface{}, ok bool) {
// Contains checks if a key is in the cache, without updating the
// recent-ness or deleting it for being stale.
-func (c *Cache) Contains(key interface{}) bool {
+func (c *Cache[K, V]) Contains(key K) bool {
c.lock.RLock()
containKey := c.lru.Contains(key)
c.lock.RUnlock()
@@ -11933,7 +11939,7 @@ func (c *Cache) Contains(key interface{}) bool {
// Peek returns the key value (or undefined if not found) without updating
// the "recently used"-ness of the key.
-func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
+func (c *Cache[K, V]) Peek(key K) (value V, ok bool) {
c.lock.RLock()
value, ok = c.lru.Peek(key)
c.lock.RUnlock()
@@ -11943,8 +11949,9 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
// ContainsOrAdd checks if a key is in the cache without updating the
// recent-ness or deleting it for being stale, and if not, adds the value.
// Returns whether found and whether an eviction occurred.
-func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
- var k, v interface{}
+func (c *Cache[K, V]) ContainsOrAdd(key K, value V) (ok, evicted bool) {
+ var k K
+ var v V
c.lock.Lock()
if c.lru.Contains(key) {
c.lock.Unlock()
@@ -11965,8 +11972,9 @@ func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
// PeekOrAdd checks if a key is in the cache without updating the
// recent-ness or deleting it for being stale, and if not, adds the value.
// Returns whether found and whether an eviction occurred.
-func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
- var k, v interface{}
+func (c *Cache[K, V]) PeekOrAdd(key K, value V) (previous V, ok, evicted bool) {
+ var k K
+ var v V
c.lock.Lock()
previous, ok = c.lru.Peek(key)
if ok {
@@ -11982,12 +11990,13 @@ func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evi
if c.onEvictedCB != nil && evicted {
c.onEvictedCB(k, v)
}
- return nil, false, evicted
+ return
}
// Remove removes the provided key from the cache.
-func (c *Cache) Remove(key interface{}) (present bool) {
- var k, v interface{}
+func (c *Cache[K, V]) Remove(key K) (present bool) {
+ var k K
+ var v V
c.lock.Lock()
present = c.lru.Remove(key)
if c.onEvictedCB != nil && present {
@@ -12002,8 +12011,9 @@ func (c *Cache) Remove(key interface{}) (present bool) {
}
// Resize changes the cache size.
-func (c *Cache) Resize(size int) (evicted int) {
- var ks, vs []interface{}
+func (c *Cache[K, V]) Resize(size int) (evicted int) {
+ var ks []K
+ var vs []V
c.lock.Lock()
evicted = c.lru.Resize(size)
if c.onEvictedCB != nil && evicted > 0 {
@@ -12020,8 +12030,9 @@ func (c *Cache) Resize(size int) (evicted int) {
}
// RemoveOldest removes the oldest item from the cache.
-func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) {
- var k, v interface{}
+func (c *Cache[K, V]) RemoveOldest() (key K, value V, ok bool) {
+ var k K
+ var v V
c.lock.Lock()
key, value, ok = c.lru.RemoveOldest()
if c.onEvictedCB != nil && ok {
@@ -12036,7 +12047,7 @@ func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) {
}
// GetOldest returns the oldest entry
-func (c *Cache) GetOldest() (key, value interface{}, ok bool) {
+func (c *Cache[K, V]) GetOldest() (key K, value V, ok bool) {
c.lock.RLock()
key, value, ok = c.lru.GetOldest()
c.lock.RUnlock()
@@ -12044,7 +12055,7 @@ func (c *Cache) GetOldest() (key, value interface{}, ok bool) {
}
// Keys returns a slice of the keys in the cache, from oldest to newest.
-func (c *Cache) Keys() []interface{} {
+func (c *Cache[K, V]) Keys() []K {
c.lock.RLock()
keys := c.lru.Keys()
c.lock.RUnlock()
@@ -12052,7 +12063,7 @@ func (c *Cache) Keys() []interface{} {
}
// Len returns the number of items in the cache.
-func (c *Cache) Len() int {
+func (c *Cache[K, V]) Len() int {
c.lock.RLock()
length := c.lru.Len()
c.lock.RUnlock()
@@ -12060,7 +12071,7 @@ func (c *Cache) Len() int {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-lru_test.go - github.com/hashicorp/golang-lru
+lru_test.go - github.com/hashicorp/golang-lru/v2
package lru
import (
@@ -12068,7 +12079,7 @@ import (
)
func BenchmarkLRU_Rand(b *testing.B) {
- l, err := New(8192)
+ l, err := New[int64, int64](8192)
if err != nil {
b.Fatalf("err: %v", err)
}
@@ -12097,7 +12108,7 @@ func BenchmarkLRU_Rand(b *testing.B) {
}
func BenchmarkLRU_Freq(b *testing.B) {
- l, err := New(8192)
+ l, err := New[int64, int64](8192)
if err != nil {
b.Fatalf("err: %v", err)
}
@@ -12130,7 +12141,7 @@ func BenchmarkLRU_Freq(b *testing.B) {
func TestLRU(t *testing.T) {
evictCounter := 0
- onEvicted := func(k interface{}, v interface{}) {
+ onEvicted := func(k int, v int) {
if k != v {
t.Fatalf("Evict values not equal (%v!=%v)", k, v)
}
@@ -12197,7 +12208,7 @@ func TestLRU(t *testing.T) {
// test that Add returns true/false if an eviction occurred
func TestLRUAdd(t *testing.T) {
evictCounter := 0
- onEvicted := func(k interface{}, v interface{}) {
+ onEvicted := func(k int, v int) {
evictCounter++
}
@@ -12216,7 +12227,7 @@ func TestLRUAdd(t *testing.T) {
// test that Contains doesn't update recent-ness
func TestLRUContains(t *testing.T) {
- l, err := New(2)
+ l, err := New[int, int](2)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -12235,7 +12246,7 @@ func TestLRUContains(t *testing.T) {
// test that ContainsOrAdd doesn't update recent-ness
func TestLRUContainsOrAdd(t *testing.T) {
- l, err := New(2)
+ l, err := New[int, int](2)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -12265,7 +12276,7 @@ func TestLRUContainsOrAdd(t *testing.T) {
// test that PeekOrAdd doesn't update recent-ness
func TestLRUPeekOrAdd(t *testing.T) {
- l, err := New(2)
+ l, err := New[int, int](2)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -12298,7 +12309,7 @@ func TestLRUPeekOrAdd(t *testing.T) {
// test that Peek doesn't update recent-ness
func TestLRUPeek(t *testing.T) {
- l, err := New(2)
+ l, err := New[int, int](2)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -12318,7 +12329,7 @@ func TestLRUPeek(t *testing.T) {
// test that Resize can upsize and downsize
func TestLRUResize(t *testing.T) {
onEvictCounter := 0
- onEvicted := func(k interface{}, v interface{}) {
+ onEvicted := func(k int, v int) {
onEvictCounter++
}
l, err := NewWithEvict(2, onEvicted)
@@ -12355,71 +12366,227 @@ func TestLRUResize(t *testing.T) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-lru.go - github.com/hashicorp/golang-lru/simplelru
+LICENSE_list - github.com/hashicorp/golang-lru/v2/simplelru
+This license applies to simplelru/list.go
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+list.go - github.com/hashicorp/golang-lru/v2/simplelru
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE_list file.
+
+package simplelru
+
+// entry is an LRU entry
+type entry[K comparable, V any] struct {
+ // Next and previous pointers in the doubly-linked list of elements.
+ // To simplify the implementation, internally a list l is implemented
+ // as a ring, such that &l.root is both the next element of the last
+ // list element (l.Back()) and the previous element of the first list
+ // element (l.Front()).
+ next, prev *entry[K, V]
+
+ // The list to which this element belongs.
+ list *lruList[K, V]
+
+ // The LRU key of this element.
+ key K
+
+ // The value stored with this element.
+ value V
+}
+
+// prevEntry returns the previous list element or nil.
+func (e *entry[K, V]) prevEntry() *entry[K, V] {
+ if p := e.prev; e.list != nil && p != &e.list.root {
+ return p
+ }
+ return nil
+}
+
+// lruList represents a doubly linked list.
+// The zero value for lruList is an empty list ready to use.
+type lruList[K comparable, V any] struct {
+ root entry[K, V] // sentinel list element, only &root, root.prev, and root.next are used
+ len int // current list length excluding (this) sentinel element
+}
+
+// init initializes or clears list l.
+func (l *lruList[K, V]) init() *lruList[K, V] {
+ l.root.next = &l.root
+ l.root.prev = &l.root
+ l.len = 0
+ return l
+}
+
+// newList returns an initialized list.
+func newList[K comparable, V any]() *lruList[K, V] { return new(lruList[K, V]).init() }
+
+// length returns the number of elements of list l.
+// The complexity is O(1).
+func (l *lruList[K, V]) length() int { return l.len }
+
+// back returns the last element of list l or nil if the list is empty.
+func (l *lruList[K, V]) back() *entry[K, V] {
+ if l.len == 0 {
+ return nil
+ }
+ return l.root.prev
+}
+
+// lazyInit lazily initializes a zero List value.
+func (l *lruList[K, V]) lazyInit() {
+ if l.root.next == nil {
+ l.init()
+ }
+}
+
+// insert inserts e after at, increments l.len, and returns e.
+func (l *lruList[K, V]) insert(e, at *entry[K, V]) *entry[K, V] {
+ e.prev = at
+ e.next = at.next
+ e.prev.next = e
+ e.next.prev = e
+ e.list = l
+ l.len++
+ return e
+}
+
+// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
+func (l *lruList[K, V]) insertValue(k K, v V, at *entry[K, V]) *entry[K, V] {
+ return l.insert(&entry[K, V]{value: v, key: k}, at)
+}
+
+// remove removes e from its list, decrements l.len
+func (l *lruList[K, V]) remove(e *entry[K, V]) V {
+ e.prev.next = e.next
+ e.next.prev = e.prev
+ e.next = nil // avoid memory leaks
+ e.prev = nil // avoid memory leaks
+ e.list = nil
+ l.len--
+
+ return e.value
+}
+
+// move moves e to next to at.
+func (l *lruList[K, V]) move(e, at *entry[K, V]) {
+ if e == at {
+ return
+ }
+ e.prev.next = e.next
+ e.next.prev = e.prev
+
+ e.prev = at
+ e.next = at.next
+ e.prev.next = e
+ e.next.prev = e
+}
+
+// pushFront inserts a new element e with value v at the front of list l and returns e.
+func (l *lruList[K, V]) pushFront(k K, v V) *entry[K, V] {
+ l.lazyInit()
+ return l.insertValue(k, v, &l.root)
+}
+
+// moveToFront moves element e to the front of list l.
+// If e is not an element of l, the list is not modified.
+// The element must not be nil.
+func (l *lruList[K, V]) moveToFront(e *entry[K, V]) {
+ if e.list != l || l.root.next == e {
+ return
+ }
+ // see comment in List.Remove about initialization of l
+ l.move(e, &l.root)
+}
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+lru.go - github.com/hashicorp/golang-lru/v2/simplelru
package simplelru
import (
- "container/list"
"errors"
)
// EvictCallback is used to get a callback when a cache entry is evicted
-type EvictCallback func(key interface{}, value interface{})
+type EvictCallback[K comparable, V any] func(key K, value V)
// LRU implements a non-thread safe fixed size LRU cache
-type LRU struct {
+type LRU[K comparable, V any] struct {
size int
- evictList *list.List
- items map[interface{}]*list.Element
- onEvict EvictCallback
-}
-
-// entry is used to hold a value in the evictList
-type entry struct {
- key interface{}
- value interface{}
+ evictList *lruList[K, V]
+ items map[K]*entry[K, V]
+ onEvict EvictCallback[K, V]
}
// NewLRU constructs an LRU of the given size
-func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
+func NewLRU[K comparable, V any](size int, onEvict EvictCallback[K, V]) (*LRU[K, V], error) {
if size <= 0 {
return nil, errors.New("must provide a positive size")
}
- c := &LRU{
+
+ c := &LRU[K, V]{
size: size,
- evictList: list.New(),
- items: make(map[interface{}]*list.Element),
+ evictList: newList[K, V](),
+ items: make(map[K]*entry[K, V]),
onEvict: onEvict,
}
return c, nil
}
// Purge is used to completely clear the cache.
-func (c *LRU) Purge() {
+func (c *LRU[K, V]) Purge() {
for k, v := range c.items {
if c.onEvict != nil {
- c.onEvict(k, v.Value.(*entry).value)
+ c.onEvict(k, v.value)
}
delete(c.items, k)
}
- c.evictList.Init()
+ c.evictList.init()
}
// Add adds a value to the cache. Returns true if an eviction occurred.
-func (c *LRU) Add(key, value interface{}) (evicted bool) {
+func (c *LRU[K, V]) Add(key K, value V) (evicted bool) {
// Check for existing item
if ent, ok := c.items[key]; ok {
- c.evictList.MoveToFront(ent)
- ent.Value.(*entry).value = value
+ c.evictList.moveToFront(ent)
+ ent.value = value
return false
}
// Add new item
- ent := &entry{key, value}
- entry := c.evictList.PushFront(ent)
- c.items[key] = entry
+ ent := c.evictList.pushFront(key, value)
+ c.items[key] = ent
- evict := c.evictList.Len() > c.size
+ evict := c.evictList.length() > c.size
// Verify size not exceeded
if evict {
c.removeOldest()
@@ -12428,37 +12595,34 @@ func (c *LRU) Add(key, value interface{}) (evicted bool) {
}
// Get looks up a key's value from the cache.
-func (c *LRU) Get(key interface{}) (value interface{}, ok bool) {
+func (c *LRU[K, V]) Get(key K) (value V, ok bool) {
if ent, ok := c.items[key]; ok {
- c.evictList.MoveToFront(ent)
- if ent.Value.(*entry) == nil {
- return nil, false
- }
- return ent.Value.(*entry).value, true
+ c.evictList.moveToFront(ent)
+ return ent.value, true
}
return
}
// Contains checks if a key is in the cache, without updating the recent-ness
// or deleting it for being stale.
-func (c *LRU) Contains(key interface{}) (ok bool) {
+func (c *LRU[K, V]) Contains(key K) (ok bool) {
_, ok = c.items[key]
return ok
}
// Peek returns the key value (or undefined if not found) without updating
// the "recently used"-ness of the key.
-func (c *LRU) Peek(key interface{}) (value interface{}, ok bool) {
- var ent *list.Element
+func (c *LRU[K, V]) Peek(key K) (value V, ok bool) {
+ var ent *entry[K, V]
if ent, ok = c.items[key]; ok {
- return ent.Value.(*entry).value, true
+ return ent.value, true
}
- return nil, ok
+ return
}
// Remove removes the provided key from the cache, returning if the
// key was contained.
-func (c *LRU) Remove(key interface{}) (present bool) {
+func (c *LRU[K, V]) Remove(key K) (present bool) {
if ent, ok := c.items[key]; ok {
c.removeElement(ent)
return true
@@ -12467,44 +12631,42 @@ func (c *LRU) Remove(key interface{}) (present bool) {
}
// RemoveOldest removes the oldest item from the cache.
-func (c *LRU) RemoveOldest() (key, value interface{}, ok bool) {
- ent := c.evictList.Back()
+func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) {
+ ent := c.evictList.back()
if ent != nil {
c.removeElement(ent)
- kv := ent.Value.(*entry)
- return kv.key, kv.value, true
+ return ent.key, ent.value, true
}
- return nil, nil, false
+ return
}
// GetOldest returns the oldest entry
-func (c *LRU) GetOldest() (key, value interface{}, ok bool) {
- ent := c.evictList.Back()
+func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) {
+ ent := c.evictList.back()
if ent != nil {
- kv := ent.Value.(*entry)
- return kv.key, kv.value, true
+ return ent.key, ent.value, true
}
- return nil, nil, false
+ return
}
// Keys returns a slice of the keys in the cache, from oldest to newest.
-func (c *LRU) Keys() []interface{} {
- keys := make([]interface{}, len(c.items))
+func (c *LRU[K, V]) Keys() []K {
+ keys := make([]K, c.evictList.length())
i := 0
- for ent := c.evictList.Back(); ent != nil; ent = ent.Prev() {
- keys[i] = ent.Value.(*entry).key
+ for ent := c.evictList.back(); ent != nil; ent = ent.prevEntry() {
+ keys[i] = ent.key
i++
}
return keys
}
// Len returns the number of items in the cache.
-func (c *LRU) Len() int {
- return c.evictList.Len()
+func (c *LRU[K, V]) Len() int {
+ return c.evictList.length()
}
// Resize changes the cache size.
-func (c *LRU) Resize(size int) (evicted int) {
+func (c *LRU[K, V]) Resize(size int) (evicted int) {
diff := c.Len() - size
if diff < 0 {
diff = 0
@@ -12517,55 +12679,54 @@ func (c *LRU) Resize(size int) (evicted int) {
}
// removeOldest removes the oldest item from the cache.
-func (c *LRU) removeOldest() {
- ent := c.evictList.Back()
+func (c *LRU[K, V]) removeOldest() {
+ ent := c.evictList.back()
if ent != nil {
c.removeElement(ent)
}
}
// removeElement is used to remove a given list element from the cache
-func (c *LRU) removeElement(e *list.Element) {
- c.evictList.Remove(e)
- kv := e.Value.(*entry)
- delete(c.items, kv.key)
+func (c *LRU[K, V]) removeElement(e *entry[K, V]) {
+ c.evictList.remove(e)
+ delete(c.items, e.key)
if c.onEvict != nil {
- c.onEvict(kv.key, kv.value)
+ c.onEvict(e.key, e.value)
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-lru_interface.go - github.com/hashicorp/golang-lru/simplelru
+lru_interface.go - github.com/hashicorp/golang-lru/v2/simplelru
// Package simplelru provides simple LRU implementation based on build-in container/list.
package simplelru
// LRUCache is the interface for simple LRU cache.
-type LRUCache interface {
+type LRUCache[K comparable, V any] interface {
// Adds a value to the cache, returns true if an eviction occurred and
// updates the "recently used"-ness of the key.
- Add(key, value interface{}) bool
+ Add(key K, value V) bool
// Returns key's value from the cache and
// updates the "recently used"-ness of the key. #value, isFound
- Get(key interface{}) (value interface{}, ok bool)
+ Get(key K) (value V, ok bool)
// Checks if a key exists in cache without updating the recent-ness.
- Contains(key interface{}) (ok bool)
+ Contains(key K) (ok bool)
// Returns key's value without updating the "recently used"-ness of the key.
- Peek(key interface{}) (value interface{}, ok bool)
+ Peek(key K) (value V, ok bool)
// Removes a key from the cache.
- Remove(key interface{}) bool
+ Remove(key K) bool
// Removes the oldest entry from cache.
- RemoveOldest() (interface{}, interface{}, bool)
+ RemoveOldest() (K, V, bool)
// Returns the oldest entry from the cache. #key, value, isFound
- GetOldest() (interface{}, interface{}, bool)
+ GetOldest() (K, V, bool)
// Returns a slice of the keys in the cache, from oldest to newest.
- Keys() []interface{}
+ Keys() []K
// Returns the number of items in the cache.
Len() int
@@ -12578,14 +12739,14 @@ type LRUCache interface {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-lru_test.go - github.com/hashicorp/golang-lru/simplelru
+lru_test.go - github.com/hashicorp/golang-lru/v2/simplelru
package simplelru
import "testing"
func TestLRU(t *testing.T) {
evictCounter := 0
- onEvicted := func(k interface{}, v interface{}) {
+ onEvicted := func(k int, v int) {
if k != v {
t.Fatalf("Evict values not equal (%v!=%v)", k, v)
}
@@ -12657,7 +12818,7 @@ func TestLRU(t *testing.T) {
}
func TestLRU_GetOldest_RemoveOldest(t *testing.T) {
- l, err := NewLRU(128, nil)
+ l, err := NewLRU[int, int](128, nil)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -12668,7 +12829,7 @@ func TestLRU_GetOldest_RemoveOldest(t *testing.T) {
if !ok {
t.Fatalf("missing")
}
- if k.(int) != 128 {
+ if k != 128 {
t.Fatalf("bad: %v", k)
}
@@ -12676,7 +12837,7 @@ func TestLRU_GetOldest_RemoveOldest(t *testing.T) {
if !ok {
t.Fatalf("missing")
}
- if k.(int) != 128 {
+ if k != 128 {
t.Fatalf("bad: %v", k)
}
@@ -12684,7 +12845,7 @@ func TestLRU_GetOldest_RemoveOldest(t *testing.T) {
if !ok {
t.Fatalf("missing")
}
- if k.(int) != 129 {
+ if k != 129 {
t.Fatalf("bad: %v", k)
}
}
@@ -12692,7 +12853,7 @@ func TestLRU_GetOldest_RemoveOldest(t *testing.T) {
// Test that Add returns true/false if an eviction occurred
func TestLRU_Add(t *testing.T) {
evictCounter := 0
- onEvicted := func(k interface{}, v interface{}) {
+ onEvicted := func(k int, v int) {
evictCounter++
}
@@ -12711,7 +12872,7 @@ func TestLRU_Add(t *testing.T) {
// Test that Contains doesn't update recent-ness
func TestLRU_Contains(t *testing.T) {
- l, err := NewLRU(2, nil)
+ l, err := NewLRU[int, int](2, nil)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -12730,7 +12891,7 @@ func TestLRU_Contains(t *testing.T) {
// Test that Peek doesn't update recent-ness
func TestLRU_Peek(t *testing.T) {
- l, err := NewLRU(2, nil)
+ l, err := NewLRU[int, int](2, nil)
if err != nil {
t.Fatalf("err: %v", err)
}
@@ -12750,7 +12911,7 @@ func TestLRU_Peek(t *testing.T) {
// Test that Resize can upsize and downsize
func TestLRU_Resize(t *testing.T) {
onEvictCounter := 0
- onEvicted := func(k interface{}, v interface{}) {
+ onEvicted := func(k int, v int) {
onEvictCounter++
}
l, err := NewLRU(2, onEvicted)
@@ -12787,7 +12948,7 @@ func TestLRU_Resize(t *testing.T) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-testing.go - github.com/hashicorp/golang-lru
+testing.go - github.com/hashicorp/golang-lru/v2
package lru
import (