@@ -38,6 +38,15 @@ func (l *List[K, V]) Insert(e *Elem[K, V]) *Elem[K, V] {
3838 return e
3939}
4040
41+ // Remove removes e from its list, decrements l's size.
42+ func (l * List [K , V ]) Remove (e * Elem [K , V ]) {
43+ e .Prev .Next = e .Next
44+ e .Next .Prev = e .Prev
45+ e .Prev = nil // Avoid memory leaks
46+ e .Next = nil // Avoid memory leaks
47+ l .Size --
48+ }
49+
4150// Update e to next to root.
4251func (l * List [K , V ]) Update (e * Elem [K , V ]) {
4352 if l .Root .Next == e {
@@ -51,42 +60,17 @@ func (l *List[K, V]) Update(e *Elem[K, V]) {
5160 e .Next .Prev = e
5261}
5362
54- // Remove removes e from its list, decrements l's size.
55- func (l * List [K , V ]) Remove (e * Elem [K , V ]) {
56- e .Prev .Next = e .Next
57- e .Next .Prev = e .Prev
58- e .Prev = nil // Avoid memory leaks
59- e .Next = nil // Avoid memory leaks
60- l .Size --
61- }
62-
6363// Lru cache. It is safe for concurrent access.
6464type Lru [K comparable , V any ] struct {
65- // Size is the maximum number of cache entries before
66- // an item is evicted. Zero means no limit.
65+ // Drop is called automatically when an elem is deleted.
66+ Drop func (k K , v V )
67+ // Size is the maximum number of cache entries before an item is evicted. Zero means no limit.
6768 Size int
6869 List * List [K , V ]
6970 C map [K ]* Elem [K , V ]
7071 M * sync.Mutex
7172}
7273
73- // Set adds a value to the cache.
74- func (l * Lru [K , V ]) Set (k K , v V ) {
75- l .M .Lock ()
76- defer l .M .Unlock ()
77- if e , ok := l .C [k ]; ok {
78- l .List .Update (e )
79- e .K = k
80- e .V = v
81- return
82- }
83- if l .List .Size == l .Size {
84- delete (l .C , l .List .Root .Prev .K )
85- l .List .Remove (l .List .Root .Prev )
86- }
87- l .C [k ] = l .List .Insert (& Elem [K , V ]{K : k , V : v })
88- }
89-
9074// Get looks up a key's value from the cache.
9175func (l * Lru [K , V ]) GetExists (k K ) (v V , ok bool ) {
9276 l .M .Lock ()
@@ -111,21 +95,47 @@ func (l *Lru[K, V]) Del(k K) {
11195 l .M .Lock ()
11296 defer l .M .Unlock ()
11397 if e , ok := l .C [k ]; ok {
98+ l .Drop (k , e .V )
11499 delete (l .C , k )
115100 l .List .Remove (e )
116101 }
117102}
118103
104+ // Has returns true if a key exists.
105+ func (l * Lru [K , V ]) Has (k K ) bool {
106+ _ , b := l .C [k ]
107+ return b
108+ }
109+
119110// Len returns the number of items in the cache.
120111func (l * Lru [K , V ]) Len () int {
121112 l .M .Lock ()
122113 defer l .M .Unlock ()
123114 return l .List .Size
124115}
125116
117+ // Set adds a value to the cache.
118+ func (l * Lru [K , V ]) Set (k K , v V ) {
119+ l .M .Lock ()
120+ defer l .M .Unlock ()
121+ if e , ok := l .C [k ]; ok {
122+ l .List .Update (e )
123+ e .K = k
124+ e .V = v
125+ return
126+ }
127+ if l .List .Size == l .Size {
128+ l .Drop (l .List .Root .Prev .K , l .List .Root .Prev .V )
129+ delete (l .C , l .List .Root .Prev .K )
130+ l .List .Remove (l .List .Root .Prev )
131+ }
132+ l .C [k ] = l .List .Insert (& Elem [K , V ]{K : k , V : v })
133+ }
134+
126135// New returns a new LRU cache. If size is zero, the cache has no limit.
127136func New [K comparable , V any ](size int ) * Lru [K , V ] {
128137 return & Lru [K , V ]{
138+ Drop : func (k K , v V ) {},
129139 Size : size ,
130140 List : new (List [K , V ]).Init (),
131141 C : map [K ]* Elem [K , V ]{},
0 commit comments