@@ -5,6 +5,7 @@ use lru::LruCache;
55#[ cfg( feature = "ttl-cache" ) ]
66use std:: collections:: VecDeque ;
77use std:: fmt:: Debug ;
8+ use std:: marker:: PhantomData ;
89use thiserror:: Error ;
910#[ cfg( feature = "ttl-cache" ) ]
1011use std:: ops:: Add ;
@@ -20,8 +21,8 @@ pub trait CacheBacking<K, V>
2021 fn get ( & mut self , key : & K ) -> Result < Option < & V > , BackingError > ;
2122 fn set ( & mut self , key : K , value : V , meta : Option < Self :: Meta > ) -> Result < Option < V > , BackingError > ;
2223 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 > ;
2526 fn clear ( & mut self ) -> Result < ( ) , BackingError > ;
2627}
2728
@@ -62,11 +63,12 @@ impl<
6263 Ok ( self . lru . pop ( key) )
6364 }
6465
65- fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > {
66+ fn contains_key ( & mut self , key : & K ) -> Result < bool , BackingError > {
6667 Ok ( self . lru . contains ( & key. clone ( ) ) )
6768 }
6869
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 ( ) ;
7072 let keys = self . lru . iter ( )
7173 . filter_map ( |( key, value) | {
7274 if predicate ( ( key, value) ) {
7880 . cloned ( )
7981 . collect :: < Vec < K > > ( ) ;
8082 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" ) ) )
8285 }
83- Ok ( ( ) )
86+ Ok ( removed )
8487 }
8588
8689 fn clear ( & mut self ) -> Result < ( ) , BackingError > {
@@ -108,10 +111,15 @@ impl<
108111}
109112
110113#[ 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 > ,
112120 ttl : Duration ,
113121 expiry_queue : VecDeque < TTlEntry < K > > ,
114- map : HashMap < K , ( V , Instant ) > ,
122+ map : B ,
115123}
116124
117125#[ cfg( feature = "ttl-cache" ) ]
@@ -154,25 +162,26 @@ impl From<Duration> for TtlMeta {
154162
155163#[ cfg( feature = "ttl-cache" ) ]
156164impl <
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 > {
160169 type Meta = TtlMeta ;
161170
162171 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) ?
165174 . map ( |( value, _) | value) )
166175 }
167176
168177 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) ?
171180 . map ( |( value, _) | value) )
172181 }
173182
174183 fn set ( & mut self , key : K , value : V , meta : Option < Self :: Meta > ) -> Result < Option < V > , BackingError > {
175- self . remove_old ( ) ;
184+ self . remove_old ( ) ? ;
176185 let ttl = if let Some ( meta) = meta {
177186 meta. ttl
178187 } else {
@@ -184,66 +193,77 @@ impl<
184193 }
185194
186195 fn remove ( & mut self , key : & K ) -> Result < Option < V > , BackingError > {
187- self . remove_old ( ) ;
196+ self . remove_old ( ) ? ;
188197 Ok ( self . remove_key ( key) ?)
189198 }
190199
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 ( ) )
196203 }
197204
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 {
211209 // 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) ) ;
213212 }
214- Ok ( ( ) )
213+ Ok ( mapped )
215214 }
216215
217216 fn clear ( & mut self ) -> Result < ( ) , BackingError > {
218217 self . expiry_queue . clear ( ) ;
219- self . map . clear ( ) ;
218+ self . map . clear ( ) ? ;
220219 Ok ( ( ) )
221220 }
222221}
223222
224223#[ 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 > {
227245 TtlCacheBacking {
246+ phantom : Default :: default ( ) ,
228247 ttl,
229- map : HashMap :: new ( ) ,
248+ map : backing ,
230249 expiry_queue : VecDeque :: new ( ) ,
231250 }
232251 }
233252
234- fn remove_old ( & mut self ) {
253+ fn remove_old ( & mut self ) -> Result < ( ) , BackingError > {
235254 let now = Instant :: now ( ) ;
236255 while let Some ( entry) = self . expiry_queue . pop_front ( ) {
237256 if now. lt ( & entry. expiry ) {
238257 self . expiry_queue . push_front ( entry) ;
239258 break ;
240259 }
241- self . map . remove ( & entry. key ) ;
260+ self . map . remove ( & entry. key ) ? ;
242261 }
262+ Ok ( ( ) )
243263 }
244264
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 ) ? ;
247267 let res = self . cleanup_expiry ( entry, & key) ;
248268 match self . expiry_queue . binary_search_by_key ( & expiry, |entry| entry. expiry ) {
249269 Ok ( found) => {
@@ -256,24 +276,24 @@ impl<K: Eq + Hash + Sized + Clone + Send, V: Sized + Clone + Send> TtlCacheBacki
256276 res
257277 }
258278
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) ? ;
261281 self . cleanup_expiry ( entry, key)
262282 }
263283
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 > {
265285 if let Some ( ( value, old_expiry) ) = entry {
266286 match self . expiry_queue . binary_search_by_key ( & old_expiry, |entry| entry. expiry ) {
267287 Ok ( found) => {
268288 let index = self . expiry_index_on_key_eq ( found, & old_expiry, key) ;
269289 if let Some ( index) = index {
270290 self . expiry_queue . remove ( index) ;
271291 } else {
272- return Err ( TtlError :: ExpiryKeyNotFound ) ;
292+ return Err ( TtlError :: ExpiryKeyNotFound . into ( ) ) ;
273293 }
274294 }
275295 Err ( _) => {
276- return Err ( TtlError :: ExpiryNotFound ) ;
296+ return Err ( TtlError :: ExpiryNotFound . into ( ) ) ;
277297 }
278298 }
279299 Ok ( Some ( value) )
@@ -340,13 +360,20 @@ impl<
340360 Ok ( self . map . remove ( key) )
341361 }
342362
343- fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > {
363+ fn contains_key ( & mut self , key : & K ) -> Result < bool , BackingError > {
344364 Ok ( self . map . contains_key ( key) )
345365 }
346366
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)
350377 }
351378
352379 fn clear ( & mut self ) -> Result < ( ) , BackingError > {
0 commit comments