@@ -5,6 +5,7 @@ use lru::LruCache;
5
5
#[ cfg( feature = "ttl-cache" ) ]
6
6
use std:: collections:: VecDeque ;
7
7
use std:: fmt:: Debug ;
8
+ use std:: marker:: PhantomData ;
8
9
use thiserror:: Error ;
9
10
#[ cfg( feature = "ttl-cache" ) ]
10
11
use std:: ops:: Add ;
@@ -20,8 +21,8 @@ pub trait CacheBacking<K, V>
20
21
fn get ( & mut self , key : & K ) -> Result < Option < & V > , BackingError > ;
21
22
fn set ( & mut self , key : K , value : V , meta : Option < Self :: Meta > ) -> Result < Option < V > , BackingError > ;
22
23
fn remove ( & mut self , key : & K ) -> Result < Option < V > , BackingError > ;
23
- fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > ;
24
- fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send + ' static > ) -> Result < ( ) , BackingError > ;
24
+ fn contains_key ( & mut self , key : & K ) -> Result < bool , BackingError > ;
25
+ fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send + Sync + ' static > ) -> Result < Vec < ( K , V ) > , BackingError > ;
25
26
fn clear ( & mut self ) -> Result < ( ) , BackingError > ;
26
27
}
27
28
@@ -62,11 +63,12 @@ impl<
62
63
Ok ( self . lru . pop ( key) )
63
64
}
64
65
65
- fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > {
66
+ fn contains_key ( & mut self , key : & K ) -> Result < bool , BackingError > {
66
67
Ok ( self . lru . contains ( & key. clone ( ) ) )
67
68
}
68
69
69
- fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) -> Result < ( ) , BackingError > {
70
+ fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send + Sync > ) -> Result < Vec < ( K , V ) > , BackingError > {
71
+ let mut removed = Vec :: new ( ) ;
70
72
let keys = self . lru . iter ( )
71
73
. filter_map ( |( key, value) | {
72
74
if predicate ( ( key, value) ) {
78
80
. cloned ( )
79
81
. collect :: < Vec < K > > ( ) ;
80
82
for key in keys. into_iter ( ) {
81
- self . lru . pop ( & key) ;
83
+ let val = self . lru . pop ( & key) ;
84
+ removed. push ( ( key, val. expect ( "LRU value is empty" ) ) )
82
85
}
83
- Ok ( ( ) )
86
+ Ok ( removed )
84
87
}
85
88
86
89
fn clear ( & mut self ) -> Result < ( ) , BackingError > {
@@ -108,10 +111,15 @@ impl<
108
111
}
109
112
110
113
#[ cfg( feature = "ttl-cache" ) ]
111
- pub struct TtlCacheBacking < K , V > {
114
+ pub struct TtlCacheBacking <
115
+ K : Clone + Eq + Hash + Send ,
116
+ V : Clone + Sized + Send ,
117
+ B : CacheBacking < K , ( V , Instant ) >
118
+ > {
119
+ phantom : PhantomData < V > ,
112
120
ttl : Duration ,
113
121
expiry_queue : VecDeque < TTlEntry < K > > ,
114
- map : HashMap < K , ( V , Instant ) > ,
122
+ map : B ,
115
123
}
116
124
117
125
#[ cfg( feature = "ttl-cache" ) ]
@@ -154,25 +162,26 @@ impl From<Duration> for TtlMeta {
154
162
155
163
#[ cfg( feature = "ttl-cache" ) ]
156
164
impl <
157
- K : Eq + Hash + Sized + Clone + Send ,
158
- V : Sized + Clone + Send
159
- > CacheBacking < K , V > for TtlCacheBacking < K , V > {
165
+ K : Clone + Eq + Hash + Send + ' static ,
166
+ V : Clone + Sized + Send + ' static ,
167
+ B : CacheBacking < K , ( V , Instant ) >
168
+ > CacheBacking < K , V > for TtlCacheBacking < K , V , B > {
160
169
type Meta = TtlMeta ;
161
170
162
171
fn get_mut ( & mut self , key : & K ) -> Result < Option < & mut V > , BackingError > {
163
- self . remove_old ( ) ;
164
- Ok ( self . map . get_mut ( key)
172
+ self . remove_old ( ) ? ;
173
+ Ok ( self . map . get_mut ( key) ?
165
174
. map ( |( value, _) | value) )
166
175
}
167
176
168
177
fn get ( & mut self , key : & K ) -> Result < Option < & V > , BackingError > {
169
- self . remove_old ( ) ;
170
- Ok ( self . map . get ( key)
178
+ self . remove_old ( ) ? ;
179
+ Ok ( self . map . get ( key) ?
171
180
. map ( |( value, _) | value) )
172
181
}
173
182
174
183
fn set ( & mut self , key : K , value : V , meta : Option < Self :: Meta > ) -> Result < Option < V > , BackingError > {
175
- self . remove_old ( ) ;
184
+ self . remove_old ( ) ? ;
176
185
let ttl = if let Some ( meta) = meta {
177
186
meta. ttl
178
187
} else {
@@ -184,66 +193,77 @@ impl<
184
193
}
185
194
186
195
fn remove ( & mut self , key : & K ) -> Result < Option < V > , BackingError > {
187
- self . remove_old ( ) ;
196
+ self . remove_old ( ) ? ;
188
197
Ok ( self . remove_key ( key) ?)
189
198
}
190
199
191
- fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > {
192
- // we cant clean old keys on this, since the self ref is not mutable :(
193
- Ok ( self . map . get ( key)
194
- . filter ( |( _, expiry) | Instant :: now ( ) . lt ( expiry) )
195
- . is_some ( ) )
200
+ fn contains_key ( & mut self , key : & K ) -> Result < bool , BackingError > {
201
+ self . remove_old ( ) ?;
202
+ Ok ( self . map . get ( key) ?. is_some ( ) )
196
203
}
197
204
198
- fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) -> Result < ( ) , BackingError > {
199
- let keys = self . map . iter ( )
200
- . filter_map ( |( key, ( value, _) ) | {
201
- if predicate ( ( key, value) ) {
202
- Some ( key)
203
- } else {
204
- None
205
- }
206
- } )
207
- . cloned ( )
208
- . collect :: < Vec < K > > ( ) ;
209
- for key in keys. into_iter ( ) {
210
- self . map . remove ( & key) ;
205
+ fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send + Sync > ) -> Result < Vec < ( K , V ) > , BackingError > {
206
+ let values = self . map . remove_if ( Box :: new ( move |( key, ( value, _) ) | predicate ( ( key, value) ) ) ) ?;
207
+ let mut mapped = Vec :: with_capacity ( values. len ( ) ) ;
208
+ for ( key, ( value, _) ) in values {
211
209
// optimize looping through expiry_queue multiple times?
212
- self . expiry_queue . retain ( |entry| entry. key . ne ( & key) )
210
+ self . expiry_queue . retain ( |entry| entry. key . ne ( & key) ) ;
211
+ mapped. push ( ( key, value) ) ;
213
212
}
214
- Ok ( ( ) )
213
+ Ok ( mapped )
215
214
}
216
215
217
216
fn clear ( & mut self ) -> Result < ( ) , BackingError > {
218
217
self . expiry_queue . clear ( ) ;
219
- self . map . clear ( ) ;
218
+ self . map . clear ( ) ? ;
220
219
Ok ( ( ) )
221
220
}
222
221
}
223
222
224
223
#[ cfg( feature = "ttl-cache" ) ]
225
- impl < K : Eq + Hash + Sized + Clone + Send , V : Sized + Clone + Send > TtlCacheBacking < K , V > {
226
- pub fn new ( ttl : Duration ) -> TtlCacheBacking < K , V > {
224
+ impl <
225
+ K : Eq + Hash + Sized + Clone + Send ,
226
+ V : Sized + Clone + Send ,
227
+ > TtlCacheBacking < K , V , HashMapBacking < K , ( V , Instant ) > > {
228
+ pub fn new ( ttl : Duration ) -> TtlCacheBacking < K , V , HashMapBacking < K , ( V , Instant ) > > {
229
+ TtlCacheBacking {
230
+ phantom : Default :: default ( ) ,
231
+ ttl,
232
+ map : HashMapBacking :: new ( ) ,
233
+ expiry_queue : VecDeque :: new ( ) ,
234
+ }
235
+ }
236
+ }
237
+
238
+ #[ cfg( feature = "ttl-cache" ) ]
239
+ impl <
240
+ K : Eq + Hash + Sized + Clone + Send ,
241
+ V : Sized + Clone + Send ,
242
+ B : CacheBacking < K , ( V , Instant ) >
243
+ > TtlCacheBacking < K , V , B > {
244
+ pub fn with_backing ( ttl : Duration , backing : B ) -> TtlCacheBacking < K , V , B > {
227
245
TtlCacheBacking {
246
+ phantom : Default :: default ( ) ,
228
247
ttl,
229
- map : HashMap :: new ( ) ,
248
+ map : backing ,
230
249
expiry_queue : VecDeque :: new ( ) ,
231
250
}
232
251
}
233
252
234
- fn remove_old ( & mut self ) {
253
+ fn remove_old ( & mut self ) -> Result < ( ) , BackingError > {
235
254
let now = Instant :: now ( ) ;
236
255
while let Some ( entry) = self . expiry_queue . pop_front ( ) {
237
256
if now. lt ( & entry. expiry ) {
238
257
self . expiry_queue . push_front ( entry) ;
239
258
break ;
240
259
}
241
- self . map . remove ( & entry. key ) ;
260
+ self . map . remove ( & entry. key ) ? ;
242
261
}
262
+ Ok ( ( ) )
243
263
}
244
264
245
- fn replace ( & mut self , key : K , value : V , expiry : Instant ) -> Result < Option < V > , TtlError > {
246
- let entry = self . map . insert ( key. clone ( ) , ( value, expiry) ) ;
265
+ fn replace ( & mut self , key : K , value : V , expiry : Instant ) -> Result < Option < V > , BackingError > {
266
+ let entry = self . map . set ( key. clone ( ) , ( value, expiry) , None ) ? ;
247
267
let res = self . cleanup_expiry ( entry, & key) ;
248
268
match self . expiry_queue . binary_search_by_key ( & expiry, |entry| entry. expiry ) {
249
269
Ok ( found) => {
@@ -256,24 +276,24 @@ impl<K: Eq + Hash + Sized + Clone + Send, V: Sized + Clone + Send> TtlCacheBacki
256
276
res
257
277
}
258
278
259
- fn remove_key ( & mut self , key : & K ) -> Result < Option < V > , TtlError > {
260
- let entry = self . map . remove ( key) ;
279
+ fn remove_key ( & mut self , key : & K ) -> Result < Option < V > , BackingError > {
280
+ let entry = self . map . remove ( key) ? ;
261
281
self . cleanup_expiry ( entry, key)
262
282
}
263
283
264
- fn cleanup_expiry ( & mut self , entry : Option < ( V , Instant ) > , key : & K ) -> Result < Option < V > , TtlError > {
284
+ fn cleanup_expiry ( & mut self , entry : Option < ( V , Instant ) > , key : & K ) -> Result < Option < V > , BackingError > {
265
285
if let Some ( ( value, old_expiry) ) = entry {
266
286
match self . expiry_queue . binary_search_by_key ( & old_expiry, |entry| entry. expiry ) {
267
287
Ok ( found) => {
268
288
let index = self . expiry_index_on_key_eq ( found, & old_expiry, key) ;
269
289
if let Some ( index) = index {
270
290
self . expiry_queue . remove ( index) ;
271
291
} else {
272
- return Err ( TtlError :: ExpiryKeyNotFound ) ;
292
+ return Err ( TtlError :: ExpiryKeyNotFound . into ( ) ) ;
273
293
}
274
294
}
275
295
Err ( _) => {
276
- return Err ( TtlError :: ExpiryNotFound ) ;
296
+ return Err ( TtlError :: ExpiryNotFound . into ( ) ) ;
277
297
}
278
298
}
279
299
Ok ( Some ( value) )
@@ -340,13 +360,20 @@ impl<
340
360
Ok ( self . map . remove ( key) )
341
361
}
342
362
343
- fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > {
363
+ fn contains_key ( & mut self , key : & K ) -> Result < bool , BackingError > {
344
364
Ok ( self . map . contains_key ( key) )
345
365
}
346
366
347
- fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) -> Result < ( ) , BackingError > {
348
- self . map . retain ( |k, v| !predicate ( ( k, v) ) ) ;
349
- Ok ( ( ) )
367
+ fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send + Sync > ) -> Result < Vec < ( K , V ) > , BackingError > {
368
+ let removed = self . map . iter ( )
369
+ . filter ( |( k, v) | predicate ( ( k, v) ) )
370
+ . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) )
371
+ . collect :: < Vec < ( K , V ) > > ( ) ;
372
+
373
+ for ( k, _) in removed. iter ( ) {
374
+ self . map . remove ( k) ;
375
+ }
376
+ Ok ( removed)
350
377
}
351
378
352
379
fn clear ( & mut self ) -> Result < ( ) , BackingError > {
0 commit comments