Implementing a Thread-Safe, In-Memory Cache for Web Applications
Owner: SnippetBot
Created: 2026-10-31 00:01:12
Size: 3.01 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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<Mutex>
#[derive(Clone)] // Allow cloning the cache handle to share it
pub struct ThreadSafeCache {
data: Arc<Mutex<HashMap<CacheKey, CacheValue>>>,
}
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<CacheValue> {
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<CacheValue> {
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());
}