use std::collections::HashMap; use std::sync::{Arc, Mutex}; use std::fmt; // Define a simple key and value type for the cache type CacheKey = String; type CacheValue = String; // The Cache struct holds the HashMap protected by Arc #[derive(Clone)] // Allow cloning the cache handle to share it pub struct ThreadSafeCache { data: Arc>>, } impl ThreadSafeCache { pub fn new() -> Self { ThreadSafeCache { data: Arc::new(Mutex::new(HashMap::new())), } } // Inserts a key-value pair into the cache pub fn insert(&self, key: CacheKey, value: CacheValue) { let mut data_guard = self.data.lock().expect("Failed to acquire mutex lock for insert"); data_guard.insert(key, value); } // Retrieves a value from the cache pub fn get(&self, key: &CacheKey) -> Option { let data_guard = self.data.lock().expect("Failed to acquire mutex lock for get"); data_guard.get(key).cloned() // `.cloned()` to return an owned value } // Removes a key-value pair from the cache pub fn remove(&self, key: &CacheKey) -> Option { let mut data_guard = self.data.lock().expect("Failed to acquire mutex lock for remove"); data_guard.remove(key) } // Clears all entries from the cache pub fn clear(&self) { let mut data_guard = self.data.lock().expect("Failed to acquire mutex lock for clear"); data_guard.clear(); } // Get current size of the cache pub fn len(&self) -> usize { let data_guard = self.data.lock().expect("Failed to acquire mutex lock for len"); data_guard.len() } } impl fmt::Debug for ThreadSafeCache { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let data_guard = self.data.lock().expect("Failed to acquire mutex lock for debug"); write!(f, "ThreadSafeCache {{ len: {}, data: {:?} }}", data_guard.len(), &*data_guard) } } fn main() { let cache = ThreadSafeCache::new(); let shared_cache = Arc::new(cache); // Wrap in Arc to share across threads let mut handles = vec![]; for i in 0..5 { let cache_clone = Arc::clone(&shared_cache); // Clone the Arc, not the cache itself let handle = std::thread::spawn(move || { let key = format!("user:{}", i); let value = format!("Data for user {}", i); cache_clone.insert(key.clone(), value); println!("Thread {}: Inserted {}", i, key); // Simulate some reads if let Some(val) = cache_clone.get(&key) { println!("Thread {}: Retrieved {} -> {}", i, key, val); } }); handles.push(handle); } for handle in handles { handle.join().unwrap(); } println!(" Final cache state: {:?}", shared_cache.data.lock().unwrap()); println!("Cache size: {}", shared_cache.len()); shared_cache.remove(&"user:0".to_string()); println!("Cache size after removing user:0: {}", shared_cache.len()); }