Skip to content

Commit d51fb6a

Browse files
committed
Add cache management utilities
- [x] 4. Add cache management utilities - Implement `clear_cache()` function for testing and memory management - Add proper error handling for all cache operations - Ensure all cache operations are best-effort with graceful degradation
1 parent 243336e commit d51fb6a

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

.kiro/specs/crc-params-caching/tasks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
- Add error handling for lock poisoning with fallback to direct key generation
2121
- _Requirements: 1.1, 1.2, 4.1_
2222

23-
- [ ] 4. Add cache management utilities
23+
- [x] 4. Add cache management utilities
2424
- Implement `clear_cache()` function for testing and memory management
2525
- Add proper error handling for all cache operations
2626
- Ensure all cache operations are best-effort with graceful degradation

src/cache.rs

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ fn get_cache() -> &'static RwLock<HashMap<CrcParamsCacheKey, [u64; 23]>> {
4040
/// 2. If cache miss, generates keys outside of any lock
4141
/// 3. Then acquires write lock to store the generated keys
4242
///
43-
/// Falls back to direct key generation if lock poisoning occurs
43+
/// All cache operations are best-effort with graceful degradation - if any cache
44+
/// operation fails, the function falls back to direct key generation
4445
pub fn get_or_generate_keys(width: u8, poly: u64, reflected: bool) -> [u64; 23] {
4546
let cache_key = CrcParamsCacheKey::new(width, poly, reflected);
4647

4748
// Try cache read first - multiple threads can read simultaneously
49+
// If lock is poisoned or read fails, continue to key generation
4850
if let Ok(cache) = get_cache().read() {
4951
if let Some(keys) = cache.get(&cache_key) {
5052
return *keys;
@@ -55,9 +57,73 @@ pub fn get_or_generate_keys(width: u8, poly: u64, reflected: bool) -> [u64; 23]
5557
let keys = generate::keys(width, poly, reflected);
5658

5759
// Try to cache the result (best effort - if this fails, we still return valid keys)
58-
if let Ok(mut cache) = get_cache().write() {
59-
cache.insert(cache_key, keys);
60-
}
60+
// Lock poisoning or write failure doesn't affect functionality
61+
let _ = get_cache().write().map(|mut cache| {
62+
cache.insert(cache_key, keys)
63+
});
6164

6265
keys
66+
}
67+
68+
/// Clear all cached CRC parameter keys
69+
///
70+
/// This function is primarily intended for testing and memory management.
71+
/// It performs a best-effort clear operation - if the cache lock is poisoned
72+
/// or unavailable, the operation silently fails without affecting program execution.
73+
///
74+
/// # Thread Safety
75+
/// This function is thread-safe and can be called concurrently with other cache operations.
76+
/// However, clearing the cache while other threads are actively using it may reduce
77+
/// performance temporarily as keys will need to be regenerated.
78+
pub fn clear_cache() {
79+
// Best-effort cache clear - if lock is poisoned or unavailable, silently continue
80+
// This ensures the function never panics or blocks program execution
81+
let _ = get_cache().write().map(|mut cache| {
82+
cache.clear()
83+
});
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use super::*;
89+
90+
#[test]
91+
fn test_cache_management_utilities() {
92+
// Clear cache to start with clean state
93+
clear_cache();
94+
95+
// Generate and cache some keys
96+
let keys1 = get_or_generate_keys(32, 0x04C11DB7, true);
97+
let keys2 = get_or_generate_keys(64, 0x42F0E1EBA9EA3693, false);
98+
99+
// Verify cache hits return same keys
100+
let cached_keys1 = get_or_generate_keys(32, 0x04C11DB7, true);
101+
let cached_keys2 = get_or_generate_keys(64, 0x42F0E1EBA9EA3693, false);
102+
103+
assert_eq!(keys1, cached_keys1);
104+
assert_eq!(keys2, cached_keys2);
105+
106+
// Clear cache
107+
clear_cache();
108+
109+
// Verify cache was cleared by checking that new calls still work
110+
// (we can't directly verify cache is empty, but we can verify functionality)
111+
let new_keys1 = get_or_generate_keys(32, 0x04C11DB7, true);
112+
assert_eq!(keys1, new_keys1); // Should be same values, but freshly generated
113+
}
114+
115+
#[test]
116+
fn test_cache_error_handling() {
117+
// Test that cache operations don't panic even if called multiple times
118+
clear_cache();
119+
clear_cache(); // Should not panic on empty cache
120+
121+
// Test that get_or_generate_keys works even after multiple clears
122+
let keys = get_or_generate_keys(32, 0x04C11DB7, true);
123+
clear_cache();
124+
let keys2 = get_or_generate_keys(32, 0x04C11DB7, true);
125+
126+
// Keys should be identical (same parameters produce same keys)
127+
assert_eq!(keys, keys2);
128+
}
63129
}

0 commit comments

Comments
 (0)