@@ -63,13 +63,14 @@ const emptyBucket = math.MaxUint32
63
63
64
64
// LRU implements a non-thread safe fixed size LRU cache.
65
65
type LRU [K comparable , V any ] struct {
66
- buckets []uint32 // contains positions of bucket lists or 'emptyBucket'
67
- elements []element [K , V ]
68
- onEvict OnEvictCallback [K , V ]
69
- hash HashKeyCallback [K ]
70
- healthCheck HealthCheckCallback [K , V ]
71
- lifetime time.Duration
72
- metrics Metrics
66
+ buckets []uint32 // contains positions of bucket lists or 'emptyBucket'
67
+ elements []element [K , V ]
68
+ onEvict OnEvictCallback [K , V ]
69
+ hash HashKeyCallback [K ]
70
+ healthCheck HealthCheckCallback [K , V ]
71
+ lifetime time.Duration
72
+ updateLifetimeOnGet bool
73
+ metrics Metrics
73
74
74
75
// used for element clearing after removal or expiration
75
76
emptyKey K
@@ -100,6 +101,10 @@ func (lru *LRU[K, V]) SetLifetime(lifetime time.Duration) {
100
101
lru .lifetime = lifetime
101
102
}
102
103
104
+ func (lru * LRU [K , V ]) SetUpdateLifetimeOnGet (update bool ) {
105
+ lru .updateLifetimeOnGet = update
106
+ }
107
+
103
108
// SetOnEvict sets the OnEvict callback function.
104
109
// The onEvict function is called for each evicted lru entry.
105
110
// Eviction happens
@@ -303,10 +308,10 @@ func (lru *LRU[K, V]) clearKeyAndValue(pos uint32) {
303
308
lru .elements [pos ].value = lru .emptyValue
304
309
}
305
310
306
- func (lru * LRU [K , V ]) findKey (hash uint32 , key K , updateLifetimeOnGet bool ) (uint32 , bool ) {
311
+ func (lru * LRU [K , V ]) findKey (hash uint32 , key K , updateLifetimeOnGet bool ) (uint32 , int64 , bool ) {
307
312
_ , startPos := lru .hashToPos (hash )
308
313
if startPos == emptyBucket {
309
- return emptyBucket , false
314
+ return emptyBucket , 0 , false
310
315
}
311
316
312
317
pos := startPos
@@ -315,18 +320,18 @@ func (lru *LRU[K, V]) findKey(hash uint32, key K, updateLifetimeOnGet bool) (uin
315
320
elem := lru .elements [pos ]
316
321
if (elem .expire != 0 && elem .expire <= now ()) || (lru .healthCheck != nil && ! lru .healthCheck (key , elem .value )) {
317
322
lru .removeAt (pos )
318
- return emptyBucket , false
323
+ return emptyBucket , elem . expire , false
319
324
}
320
325
if updateLifetimeOnGet {
321
326
lru .elements [pos ].expire = expire (lru .lifetime )
322
327
}
323
- return pos , true
328
+ return pos , elem . expire , true
324
329
}
325
330
326
331
pos = lru .elements [pos ].nextBucket
327
332
if pos == startPos {
328
333
// Key not found
329
- return emptyBucket , false
334
+ return emptyBucket , 0 , false
330
335
}
331
336
}
332
337
}
@@ -439,17 +444,24 @@ func (lru *LRU[K, V]) add(hash uint32, key K, value V) (evicted bool) {
439
444
// If the found cache item is already expired, the evict function is called
440
445
// and the return value indicates that the key was not found.
441
446
func (lru * LRU [K , V ]) Get (key K ) (value V , ok bool ) {
442
- return lru .get (lru .hash (key ), key )
447
+ value , _ , ok = lru .get (lru .hash (key ), key )
448
+ return
443
449
}
444
450
445
- func (lru * LRU [K , V ]) get (hash uint32 , key K ) (value V , ok bool ) {
446
- if pos , ok := lru .findKey (hash , key , true ); ok {
451
+ func (lru * LRU [K , V ]) GetWithLifetime (key K ) (value V , lifetime time.Time , ok bool ) {
452
+ value , expireMills , ok := lru .get (lru .hash (key ), key )
453
+ lifetime = time .UnixMilli (expireMills )
454
+ return
455
+ }
456
+
457
+ func (lru * LRU [K , V ]) get (hash uint32 , key K ) (value V , expire int64 , ok bool ) {
458
+ if pos , expire , ok := lru .findKey (hash , key , lru .updateLifetimeOnGet ); ok {
447
459
if pos != lru .head {
448
460
lru .unlinkElement (pos )
449
461
lru .setHead (pos )
450
462
}
451
463
lru .metrics .Hits ++
452
- return lru .elements [pos ].value , ok
464
+ return lru .elements [pos ].value , expire , ok
453
465
}
454
466
455
467
lru .metrics .Misses ++
@@ -463,7 +475,7 @@ func (lru *LRU[K, V]) Peek(key K) (value V, ok bool) {
463
475
}
464
476
465
477
func (lru * LRU [K , V ]) peek (hash uint32 , key K ) (value V , ok bool ) {
466
- if pos , ok := lru .findKey (hash , key , false ); ok {
478
+ if pos , _ , ok := lru .findKey (hash , key , false ); ok {
467
479
return lru .elements [pos ].value , ok
468
480
}
469
481
@@ -490,7 +502,7 @@ func (lru *LRU[K, V]) Remove(key K) (removed bool) {
490
502
}
491
503
492
504
func (lru * LRU [K , V ]) remove (hash uint32 , key K ) (removed bool ) {
493
- if pos , ok := lru .findKey (hash , key , false ); ok {
505
+ if pos , _ , ok := lru .findKey (hash , key , false ); ok {
494
506
lru .removeAt (pos )
495
507
return ok
496
508
}
0 commit comments