@@ -435,33 +435,44 @@ where
435435 }
436436
437437 pub async fn get ( & self , key : & Q ) -> Option < T > {
438- let ( result, items_to_unref, removal_futures) = {
438+ // Collect any early-return cleanup items separately to avoid holding
439+ // the lock across an await point.
440+ let early_return_cleanup = {
439441 let mut state = self . state . lock ( ) ;
440- // Check if the requested item is expired before promoting it.
441- let result = if let Some ( entry) = state. lru . peek ( key. borrow ( ) ) {
442+ if let Some ( entry) = state. lru . peek ( key. borrow ( ) ) {
442443 if self . should_evict ( state. lru . len ( ) , entry, 0 , u64:: MAX ) {
443- // Item is expired, remove it.
444444 if let Some ( ( k, eviction_item) ) = state. lru . pop_entry ( key. borrow ( ) ) {
445445 let ( data, futures) = state. remove ( k. borrow ( ) , & eviction_item, false ) ;
446446 let ( mut items, mut removals) = self . evict_items ( & mut * state) ;
447447 items. push ( data) ;
448448 removals. extend ( futures) ;
449- return {
450- Self :: unref_items ( items, removals) . await ;
451- None
452- } ;
449+ Some ( ( items, removals) )
450+ } else {
451+ None
453452 }
454- None
455453 } else {
456- // Item is valid. Promote it in LRU so it's safe from eviction.
457- state. lru . get_mut ( key. borrow ( ) ) . map ( |entry| {
458- entry. seconds_since_anchor =
459- i32:: try_from ( self . anchor_time . elapsed ( ) . as_secs ( ) ) . unwrap_or ( i32:: MAX ) ;
460- entry. data . clone ( )
461- } )
454+ None
462455 }
463456 } else {
464457 None
458+ }
459+ } ;
460+ if let Some ( ( items, removals) ) = early_return_cleanup {
461+ Self :: unref_items ( items, removals) . await ;
462+ return None ;
463+ }
464+
465+ let ( result, items_to_unref, removal_futures) = {
466+ let mut state = self . state . lock ( ) ;
467+ let result = if let Some ( _entry) = state. lru . peek ( key. borrow ( ) ) {
468+ // Item is valid. Promote it in LRU so it's safe from eviction.
469+ state. lru . get_mut ( key. borrow ( ) ) . map ( |entry| {
470+ entry. seconds_since_anchor =
471+ i32:: try_from ( self . anchor_time . elapsed ( ) . as_secs ( ) ) . unwrap_or ( i32:: MAX ) ;
472+ entry. data . clone ( )
473+ } )
474+ } else {
475+ None
465476 } ;
466477 // Evict other items if needed
467478 let ( items_to_unref, removal_futures) = self . evict_items ( & mut * state) ;
0 commit comments