@@ -482,7 +482,9 @@ where
482482
483483 /// Applies a function to all values in the cache.
484484 ///
485- /// This method marks all entries as visited.
485+ /// This method safely processes values by collecting them with the lock held,
486+ /// then releasing the lock before applying the function to each value individually.
487+ /// If the function modifies the values, the changes are saved back to the cache.
486488 ///
487489 /// # Examples
488490 ///
@@ -500,17 +502,37 @@ where
500502 /// assert_eq!(cache.get(&"key1".to_string()), Some("value1_updated".to_string()));
501503 /// assert_eq!(cache.get(&"key2".to_string()), Some("value2_updated".to_string()));
502504 /// ```
503- pub fn for_each_value < F > ( & self , f : F )
505+ pub fn for_each_value < F > ( & self , mut f : F )
504506 where
505507 F : FnMut ( & mut V ) ,
508+ V : Clone ,
506509 {
507- let mut guard = self . locked_cache ( ) ;
508- guard. values_mut ( ) . for_each ( f) ;
510+ // First, safely collect all keys and values while holding the lock
511+ let entries = self . with_lock ( |inner_cache| {
512+ inner_cache
513+ . iter ( )
514+ . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) )
515+ . collect :: < Vec < ( K , V ) > > ( )
516+ } ) ;
517+
518+ // Process each value outside the lock
519+ let mut updated_entries = Vec :: new ( ) ;
520+ for ( key, mut value) in entries {
521+ f ( & mut value) ;
522+ updated_entries. push ( ( key, value) ) ;
523+ }
524+
525+ // Update any changed values back to the cache
526+ for ( key, value) in updated_entries {
527+ self . insert ( key, value) ;
528+ }
509529 }
510530
511531 /// Applies a function to all key-value pairs in the cache.
512532 ///
513- /// This method marks all entries as visited.
533+ /// This method safely processes key-value pairs by collecting them with the lock held,
534+ /// then releasing the lock before applying the function to each pair individually.
535+ /// If the function modifies the values, the changes are saved back to the cache.
514536 ///
515537 /// # Examples
516538 ///
@@ -530,12 +552,31 @@ where
530552 /// assert_eq!(cache.get(&"key1".to_string()), Some("value1_special".to_string()));
531553 /// assert_eq!(cache.get(&"key2".to_string()), Some("value2".to_string()));
532554 /// ```
533- pub fn for_each_entry < F > ( & self , f : F )
555+ pub fn for_each_entry < F > ( & self , mut f : F )
534556 where
535557 F : FnMut ( ( & K , & mut V ) ) ,
558+ V : Clone ,
536559 {
537- let mut guard = self . locked_cache ( ) ;
538- guard. iter_mut ( ) . for_each ( f) ;
560+ // First, safely collect all keys and values while holding the lock
561+ let entries = self . with_lock ( |inner_cache| {
562+ inner_cache
563+ . iter ( )
564+ . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) )
565+ . collect :: < Vec < ( K , V ) > > ( )
566+ } ) ;
567+
568+ // Process each entry outside the lock
569+ let mut updated_entries = Vec :: new ( ) ;
570+ for ( key, mut value) in entries {
571+ let key_ref = & key;
572+ f ( ( key_ref, & mut value) ) ;
573+ updated_entries. push ( ( key, value) ) ;
574+ }
575+
576+ // Update any changed values back to the cache
577+ for ( key, value) in updated_entries {
578+ self . insert ( key, value) ;
579+ }
539580 }
540581
541582 /// Gets exclusive access to the underlying cache to perform multiple operations atomically.
@@ -570,7 +611,9 @@ where
570611 ///
571612 /// Removes all entries for which the provided function returns `false`.
572613 /// The elements are visited in arbitrary, unspecified order.
573- /// This operation acquires a lock on the entire cache.
614+ /// This operation first collects entries while holding the lock, then evaluates
615+ /// the predicate on those entries outside the lock, and finally acquires the lock
616+ /// again only for each removal operation.
574617 ///
575618 /// # Examples
576619 ///
@@ -589,12 +632,27 @@ where
589632 /// assert!(cache.contains_key(&"key2".to_string()));
590633 /// assert!(cache.contains_key(&"key3".to_string()));
591634 /// ```
592- pub fn retain < F > ( & self , f : F )
635+ pub fn retain < F > ( & self , mut f : F )
593636 where
594637 F : FnMut ( & K , & V ) -> bool ,
638+ V : Clone ,
595639 {
596- let mut guard = self . locked_cache ( ) ;
597- guard. retain ( f) ;
640+ // First, safely collect all entries while holding the lock
641+ let entries = self . with_lock ( |inner_cache| {
642+ inner_cache
643+ . iter ( )
644+ . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) )
645+ . collect :: < Vec < ( K , V ) > > ( )
646+ } ) ;
647+
648+ // Now check each entry against the predicate without holding the lock
649+ for ( key, value) in entries {
650+ if !f ( & key, & value) {
651+ // Remove entries that don't match the predicate
652+ // This acquires the lock for each removal operation
653+ self . remove ( & key) ;
654+ }
655+ }
598656 }
599657}
600658
0 commit comments