@@ -29,7 +29,8 @@ pub(crate) struct LruEntry<K, V> {
29
29
pub val : mem:: MaybeUninit < V > ,
30
30
pub prev : * mut LruEntry < K , V > ,
31
31
pub next : * mut LruEntry < K , V > ,
32
-
32
+ /// 带ttl的过期时间,单位秒
33
+ /// 如果为u64::MAX,则表示不过期
33
34
#[ cfg( feature = "ttl" ) ]
34
35
pub expire : u64 ,
35
36
}
@@ -115,12 +116,15 @@ pub struct LruCache<K, V, S> {
115
116
head : * mut LruEntry < K , V > ,
116
117
/// 双向列表的尾
117
118
tail : * mut LruEntry < K , V > ,
118
-
119
+ /// 下一次检查的时间点,如果大于该时间点则全部检查是否过期
119
120
#[ cfg( feature = "ttl" ) ]
120
121
check_next : u64 ,
121
-
122
+ /// 每次大检查点的时间间隔,如果不想启用该特性,可以将该值设成u64::MAX
122
123
#[ cfg( feature = "ttl" ) ]
123
124
check_step : u64 ,
125
+ /// 所有节点中是否存在带ttl的结点,如果均为普通的元素,则过期的将不进行检查
126
+ #[ cfg( feature = "ttl" ) ]
127
+ has_ttl : bool ,
124
128
}
125
129
126
130
impl < K : Hash + Eq , V > Default for LruCache < K , V , DefaultHasher > {
@@ -155,6 +159,8 @@ impl<K, V, S> LruCache<K, V, S> {
155
159
check_step : DEFAULT_CHECK_STEP ,
156
160
#[ cfg( feature = "ttl" ) ]
157
161
check_next : get_timestamp ( ) +DEFAULT_CHECK_STEP ,
162
+ #[ cfg( feature = "ttl" ) ]
163
+ has_ttl : false ,
158
164
}
159
165
}
160
166
@@ -604,7 +610,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LruCache<K, V, S> {
604
610
self . detach ( node) ;
605
611
#[ cfg( feature = "ttl" ) ]
606
612
unsafe {
607
- if ( * node) . is_expire ( ) {
613
+ if self . has_ttl && ( * node) . is_expire ( ) {
608
614
self . map . remove ( KeyWrapper :: from_ref ( k) ) ;
609
615
let _ = * Box :: from_raw ( node) ;
610
616
return None ;
@@ -638,6 +644,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LruCache<K, V, S> {
638
644
/// 如果需要更新则需要手动的进行重新设置
639
645
#[ inline( always) ]
640
646
pub fn insert_with_ttl ( & mut self , k : K , v : V , ttl : u64 ) -> Option < V > {
647
+ self . has_ttl = true ;
641
648
self . _capture_insert_with_ttl ( k, v, ttl) . map ( |( _, v, _) | v)
642
649
}
643
650
@@ -719,6 +726,9 @@ impl<K: Hash + Eq, V, S: BuildHasher> LruCache<K, V, S> {
719
726
720
727
#[ cfg( feature="ttl" ) ]
721
728
pub fn clear_expire ( & mut self ) {
729
+ if !self . has_ttl {
730
+ return ;
731
+ }
722
732
let now = get_timestamp ( ) ;
723
733
if now < self . check_next {
724
734
return ;
@@ -755,6 +765,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LruCache<K, V, S> {
755
765
K : Borrow < Q > ,
756
766
Q : Hash + Eq + ?Sized , {
757
767
if let Some ( v) = self . get_node ( & k) {
768
+ self . has_ttl = true ;
758
769
unsafe {
759
770
( * v) . expire = get_timestamp ( ) . saturating_add ( expire) ;
760
771
}
@@ -1640,4 +1651,17 @@ mod tests {
1640
1651
assert_eq ! ( lru. get( "help" ) , None ) ;
1641
1652
assert_eq ! ( lru. len( ) , 0 ) ;
1642
1653
}
1654
+
1655
+
1656
+ #[ test]
1657
+ #[ cfg( feature="ttl" ) ]
1658
+ fn test_ttl_get ( ) {
1659
+ let mut lru = LruCache :: new ( 3 ) ;
1660
+ lru. insert_with_ttl ( "help" , "ok" , 1 ) ;
1661
+ lru. insert_with_ttl ( "author" , "tickbh" , 2 ) ;
1662
+ lru. insert ( "now" , "algorithm" ) ;
1663
+ assert_eq ! ( lru. get_ttl( & "help" ) , Some ( 1 ) ) ;
1664
+ assert_eq ! ( lru. get_ttl( & "author" ) , Some ( 2 ) ) ;
1665
+ assert_eq ! ( lru. get_ttl( & "now" ) , Some ( u64 :: MAX ) ) ;
1666
+ }
1643
1667
}
0 commit comments