pub struct SyncSieveCache<K, V>{ /* private fields */ }Expand description
A thread-safe wrapper around SieveCache.
This provides a thread-safe implementation of the SIEVE cache algorithm by wrapping
the standard SieveCache in an Arc<Mutex<>>. It offers the same functionality as
the underlying cache but with thread safety guarantees.
§Thread Safety
All operations acquire a lock on the entire cache, which provides strong consistency
but may become a bottleneck under high contention. For workloads with high concurrency,
consider using ShardedSieveCache instead, which partitions
the cache into multiple independently-locked segments.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
// Multiple threads can safely access the cache
cache.insert("key1".to_string(), "value1".to_string());
assert_eq!(cache.get(&"key1".to_string()), Some("value1".to_string()));Implementations§
Source§impl<K, V> SyncSieveCache<K, V>
impl<K, V> SyncSieveCache<K, V>
Sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the capacity of the cache.
§Examples
let cache = SyncSieveCache::<String, u32>::new(100).unwrap();
assert_eq!(cache.capacity(), 100);Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of cached values.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key".to_string(), "value".to_string());
assert_eq!(cache.len(), 1);Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true when no values are currently cached.
§Examples
let cache = SyncSieveCache::<String, String>::new(100).unwrap();
assert!(cache.is_empty());
cache.insert("key".to_string(), "value".to_string());
assert!(!cache.is_empty());Sourcepub fn contains_key<Q>(&self, key: &Q) -> bool
pub fn contains_key<Q>(&self, key: &Q) -> bool
Returns true if there is a value in the cache mapped to by key.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key".to_string(), "value".to_string());
assert!(cache.contains_key(&"key".to_string()));
assert!(!cache.contains_key(&"missing".to_string()));Sourcepub fn get<Q>(&self, key: &Q) -> Option<V>
pub fn get<Q>(&self, key: &Q) -> Option<V>
Gets a clone of the value in the cache mapped to by key.
If no value exists for key, this returns None.
§Note
Unlike the unwrapped SieveCache, this returns a clone of the value
rather than a reference, since the mutex guard would be dropped after
this method returns. This means that V must implement Clone.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key".to_string(), "value".to_string());
assert_eq!(cache.get(&"key".to_string()), Some("value".to_string()));
assert_eq!(cache.get(&"missing".to_string()), None);Sourcepub fn get_mut<Q, F>(&self, key: &Q, f: F) -> bool
pub fn get_mut<Q, F>(&self, key: &Q, f: F) -> bool
Gets a mutable reference to the value in the cache mapped to by key via a callback function.
If no value exists for key, the callback will not be invoked and this returns false.
Otherwise, the callback is invoked with a mutable reference to the value and this returns true.
This operation marks the entry as “visited” in the SIEVE algorithm, which affects eviction decisions.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key".to_string(), "value".to_string());
// Modify the value in-place
cache.get_mut(&"key".to_string(), |value| {
*value = "new_value".to_string();
});
assert_eq!(cache.get(&"key".to_string()), Some("new_value".to_string()));Sourcepub fn insert(&self, key: K, value: V) -> bool
pub fn insert(&self, key: K, value: V) -> bool
Maps key to value in the cache, possibly evicting old entries.
This method returns true when this is a new entry, and false if an existing entry was
updated.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
// Insert a new key
assert!(cache.insert("key1".to_string(), "value1".to_string()));
// Update an existing key
assert!(!cache.insert("key1".to_string(), "updated_value".to_string()));Sourcepub fn remove<Q>(&self, key: &Q) -> Option<V>
pub fn remove<Q>(&self, key: &Q) -> Option<V>
Removes the cache entry mapped to by key.
This method returns the value removed from the cache. If key did not map to any value,
then this returns None.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key".to_string(), "value".to_string());
// Remove an existing key
assert_eq!(cache.remove(&"key".to_string()), Some("value".to_string()));
// Attempt to remove a missing key
assert_eq!(cache.remove(&"key".to_string()), None);Sourcepub fn evict(&self) -> Option<V>
pub fn evict(&self) -> Option<V>
Removes and returns a value from the cache that was not recently accessed.
This implements the SIEVE eviction algorithm to select an entry for removal.
If no suitable value exists, this returns None.
§Examples
let cache = SyncSieveCache::new(2).unwrap();
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());
// Accessing key1 marks it as recently used
assert_eq!(cache.get(&"key1".to_string()), Some("value1".to_string()));
// Insert a new key, which should evict key2
cache.insert("key3".to_string(), "value3".to_string());
// key2 should have been evicted
assert_eq!(cache.get(&"key2".to_string()), None);Sourcepub fn clear(&self)
pub fn clear(&self)
Removes all entries from the cache.
This operation clears all stored values and resets the cache to an empty state, while maintaining the original capacity.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());
assert_eq!(cache.len(), 2);
cache.clear();
assert_eq!(cache.len(), 0);
assert!(cache.is_empty());Sourcepub fn keys(&self) -> Vec<K>
pub fn keys(&self) -> Vec<K>
Returns an iterator over all keys in the cache.
The order of keys is not specified and should not be relied upon.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());
let keys: HashSet<_> = cache.keys().into_iter().collect();
assert_eq!(keys.len(), 2);
assert!(keys.contains(&"key1".to_string()));
assert!(keys.contains(&"key2".to_string()));Sourcepub fn values(&self) -> Vec<V>where
V: Clone,
pub fn values(&self) -> Vec<V>where
V: Clone,
Returns all values in the cache.
The order of values is not specified and should not be relied upon.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());
let values: HashSet<_> = cache.values().into_iter().collect();
assert_eq!(values.len(), 2);
assert!(values.contains(&"value1".to_string()));
assert!(values.contains(&"value2".to_string()));Sourcepub fn entries(&self) -> Vec<(K, V)>where
V: Clone,
pub fn entries(&self) -> Vec<(K, V)>where
V: Clone,
Returns all key-value pairs in the cache.
The order of pairs is not specified and should not be relied upon.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());
let entries: HashMap<_, _> = cache.entries().into_iter().collect();
assert_eq!(entries.len(), 2);
assert_eq!(entries.get(&"key1".to_string()), Some(&"value1".to_string()));
assert_eq!(entries.get(&"key2".to_string()), Some(&"value2".to_string()));Sourcepub fn for_each_value<F>(&self, f: F)
pub fn for_each_value<F>(&self, f: F)
Applies a function to all values in the cache.
This method marks all entries as visited.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());
// Update all values by appending text
cache.for_each_value(|value| {
*value = format!("{}_updated", value);
});
assert_eq!(cache.get(&"key1".to_string()), Some("value1_updated".to_string()));
assert_eq!(cache.get(&"key2".to_string()), Some("value2_updated".to_string()));Sourcepub fn for_each_entry<F>(&self, f: F)
pub fn for_each_entry<F>(&self, f: F)
Applies a function to all key-value pairs in the cache.
This method marks all entries as visited.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());
// Update all values associated with keys containing '1'
cache.for_each_entry(|(key, value)| {
if key.contains('1') {
*value = format!("{}_special", value);
}
});
assert_eq!(cache.get(&"key1".to_string()), Some("value1_special".to_string()));
assert_eq!(cache.get(&"key2".to_string()), Some("value2".to_string()));Sourcepub fn with_lock<F, T>(&self, f: F) -> Twhere
F: FnOnce(&mut SieveCache<K, V>) -> T,
pub fn with_lock<F, T>(&self, f: F) -> Twhere
F: FnOnce(&mut SieveCache<K, V>) -> T,
Gets exclusive access to the underlying cache to perform multiple operations atomically.
This is useful when you need to perform a series of operations that depend on each other and you want to ensure that no other thread can access the cache between operations.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.with_lock(|inner_cache| {
// Perform multiple operations atomically
inner_cache.insert("key1".to_string(), "value1".to_string());
inner_cache.insert("key2".to_string(), "value2".to_string());
// We can check internal state mid-transaction
assert_eq!(inner_cache.len(), 2);
});Sourcepub fn retain<F>(&self, f: F)
pub fn retain<F>(&self, f: F)
Retains only the elements specified by the predicate.
Removes all entries for which the provided function returns false.
The elements are visited in arbitrary, unspecified order.
This operation acquires a lock on the entire cache.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key1".to_string(), 100);
cache.insert("key2".to_string(), 200);
cache.insert("key3".to_string(), 300);
// Keep only entries with values greater than 150
cache.retain(|_, value| *value > 150);
assert_eq!(cache.len(), 2);
assert!(!cache.contains_key(&"key1".to_string()));
assert!(cache.contains_key(&"key2".to_string()));
assert!(cache.contains_key(&"key3".to_string()));Trait Implementations§
Source§impl<K, V> Clone for SyncSieveCache<K, V>
impl<K, V> Clone for SyncSieveCache<K, V>
Source§fn clone(&self) -> SyncSieveCache<K, V>
fn clone(&self) -> SyncSieveCache<K, V>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<K, V> Debug for SyncSieveCache<K, V>
impl<K, V> Debug for SyncSieveCache<K, V>
Source§impl<K, V> From<SieveCache<K, V>> for SyncSieveCache<K, V>
impl<K, V> From<SieveCache<K, V>> for SyncSieveCache<K, V>
Source§fn from(cache: SieveCache<K, V>) -> Self
fn from(cache: SieveCache<K, V>) -> Self
Creates a new thread-safe cache from an existing SieveCache.
This allows for easily converting a single-threaded cache to a thread-safe version.
§Examples
let mut single_threaded = SieveCache::new(100).unwrap();
single_threaded.insert("key".to_string(), "value".to_string());
// Convert to thread-safe version
let thread_safe = SyncSieveCache::from(single_threaded);
assert_eq!(thread_safe.get(&"key".to_string()), Some("value".to_string()));Source§impl<K, V> From<SyncSieveCache<K, V>> for ShardedSieveCache<K, V>
impl<K, V> From<SyncSieveCache<K, V>> for ShardedSieveCache<K, V>
Source§fn from(sync_cache: SyncSieveCache<K, V>) -> Self
fn from(sync_cache: SyncSieveCache<K, V>) -> Self
Creates a new sharded cache from an existing SyncSieveCache.
This allows for upgrading a standard thread-safe cache to a more scalable sharded version.
§Examples
let sync_cache = SyncSieveCache::new(100).unwrap();
sync_cache.insert("key".to_string(), "value".to_string());
// Convert to sharded version with default sharding
let sharded_cache = ShardedSieveCache::from(sync_cache);
assert_eq!(sharded_cache.get(&"key".to_string()), Some("value".to_string()));Source§impl<K, V> IntoIterator for SyncSieveCache<K, V>
impl<K, V> IntoIterator for SyncSieveCache<K, V>
Source§fn into_iter(self) -> Self::IntoIter
fn into_iter(self) -> Self::IntoIter
Converts the cache into an iterator over its key-value pairs.
This collects all entries into a Vec and returns an iterator over that Vec.
§Examples
let cache = SyncSieveCache::new(100).unwrap();
cache.insert("key1".to_string(), "value1".to_string());
cache.insert("key2".to_string(), "value2".to_string());
// Collect into a HashMap
let map: HashMap<_, _> = cache.into_iter().collect();
assert_eq!(map.len(), 2);
assert_eq!(map.get("key1"), Some(&"value1".to_string()));