scc::HashIndex is a read-optimized version of HashMap. It uses sdd to protect entry buckets, enabling lock-free read access to individual entries via peek and peek_with.
Important: Entry Lifetime
HashIndex does not drop removed entries immediately. An entry is only dropped when the bucket is accessed again after sdd ensures no potential readers remain. This makes HashIndex unsuitable for write-heavy workloads with large entry sizes.
Iteration
Unlike HashMap, HashIndex implements the standard Iterator trait, but requires an sdd::Guard to be supplied to the iter method.
use scc::HashIndex;
use sdd::Guard;
let hashindex: HashIndex<u64, u32> = HashIndex::default();
assert!(hashindex.insert_sync(1, 0).is_ok());
// Lock-free reads
assert_eq!(hashindex.peek_with(&1, |_, v| *v).unwrap(), 0);
// Updating entries
if let Some(mut o) = hashindex.get_sync(&1) {
o.update(2); // Create a new version
}
// Standard Iterator usage
let guard = Guard::new();
let mut iter = hashindex.iter(&guard);
let entry_ref = iter.next().unwrap();
use scc::HashIndex;
use sdd::Guard;
let hashindex: HashIndex<u64, u32> = HashIndex::default();
assert!(hashindex.insert_sync(1, 0).is_ok());
// `peek` and `peek_with` are lock-free.
assert_eq!(hashindex.peek_with(&1, |_, v| *v).unwrap(), 0);
let future_insert = hashindex.insert_async(2, 1);
let future_remove = hashindex.remove_if_async(&1, |_| true);
// The `Entry` API of `HashIndex` can update an existing entry.
assert!(hashindex.insert_sync(1, 1).is_ok());
if let Some(mut o) = hashindex.get_sync(&1) {
// Create a new version of the entry.
o.update(2);
};
if let Some(mut o) = hashindex.get_sync(&1) {
// Update the entry in place.
unsafe { *o.get_mut() = 3; }
};
// An `Iterator` is implemented for `HashIndex`.
let hashindex: HashIndex<u64, u32> = HashIndex::default();
assert!(hashindex.insert_sync(1, 0).is_ok());
// Existing values can be replaced with a new one.
hashindex.get_sync(&1).unwrap().update(1);
let guard = Guard::new();
// An `Guard` has to be supplied to `iter`.
let mut iter = hashindex.iter(&guard);
let entry_ref = iter.next().unwrap();
assert_eq!(iter.next(), None);