pub struct HashMap<K, V, H = RandomState>where
K: Eq + Hash,
H: BuildHasher,{ /* private fields */ }
Expand description
Scalable concurrent hash map.
HashMap
is a concurrent and asynchronous hash map data structure that is targeted at a
highly concurrent workload. HashMap
has a dynamically sized array of buckets where a bucket
is a fixed size hash table with linear probing that can be expanded by allocating a linked list
of smaller buckets when it is full.
The key features of HashMap
- Non-sharded: the data is stored in a single array of entry buckets.
- Non-blocking resizing: resizing does not block other threads or tasks.
- Automatic resizing: it automatically grows or shrinks.
- Incremental resizing: entries in the old bucket array are incrementally relocated.
- No busy waiting: no spin-locks or hot loops to wait for desired resources.
- Linearizability:
HashMap
manipulation methods are linearizable.
The key statistics for HashMap
- The expected size of metadata for a single entry: 2-byte.
- The expected number of atomic write operations required for an operation on a single key: 2.
- The expected number of atomic variables accessed during a single key operation: 2.
- The number of entries managed by a single bucket without a linked list: 32.
- The expected maximum linked list length when a resize is triggered: log(capacity) / 8.
Locking behavior
Bucket access
Bucket arrays are protected by ebr
, thus allowing lock-free access to them.
Entry access
Each read/write access to an entry is serialized by the read-write lock in the bucket
containing the entry. There are no container-level locks, therefore, the larger the HashMap
gets, the lower the chance that the bucket-level lock being contended.
Resize
Resizing of the HashMap
is totally non-blocking and lock-free; resizing does not block any
other read/write access to the HashMap
or resizing attempts. Resizing is analogous to
pushing a new bucket array into a lock-free stack. Each individual entry in the old bucket
array will be incrementally relocated to the new bucket array on future access to the
HashMap
, and the old bucket array gets dropped when it becomes empty and unreachable.
Unwind safety
HashMap
is impervious to out-of-memory errors and panics in user specified code on one
condition; H::Hasher::hash
, K::drop
and V::drop
must not panic.
Implementations§
source§impl<K, V, H> HashMap<K, V, H>where
K: Eq + Hash,
H: BuildHasher,
impl<K, V, H> HashMap<K, V, H>where K: Eq + Hash, H: BuildHasher,
sourcepub fn with_hasher(build_hasher: H) -> Self
pub fn with_hasher(build_hasher: H) -> Self
Creates an empty HashMap
with the given BuildHasher
.
Examples
use scc::HashMap;
use std::collections::hash_map::RandomState;
let hashmap: HashMap<u64, u32, RandomState> = HashMap::with_hasher(RandomState::new());
sourcepub fn with_capacity_and_hasher(capacity: usize, build_hasher: H) -> Self
pub fn with_capacity_and_hasher(capacity: usize, build_hasher: H) -> Self
Creates an empty HashMap
with the specified capacity and BuildHasher
.
The actual capacity is equal to or greater than the specified capacity.
Examples
use scc::HashMap;
use std::collections::hash_map::RandomState;
let hashmap: HashMap<u64, u32, RandomState> =
HashMap::with_capacity_and_hasher(1000, RandomState::new());
let result = hashmap.capacity();
assert_eq!(result, 1024);
sourcepub fn reserve(
&self,
additional_capacity: usize
) -> Option<Reserve<'_, K, V, H>>
pub fn reserve( &self, additional_capacity: usize ) -> Option<Reserve<'_, K, V, H>>
Temporarily increases the minimum capacity of the HashMap
.
A Reserve
is returned if the HashMap
could increase the minimum capacity while the
increased capacity is not exclusively owned by the returned Reserve
, allowing others to
benefit from it. The memory for the additional space may not be immediately allocated if
the HashMap
is empty or currently being resized, however once the memory is reserved
eventually, the capacity will not shrink below the additional capacity until the returned
Reserve
is dropped.
Errors
Returns None
if a too large number is given.
Examples
use scc::HashMap;
let hashmap: HashMap<usize, usize> = HashMap::with_capacity(1000);
assert_eq!(hashmap.capacity(), 1024);
let reserved = hashmap.reserve(10000);
assert!(reserved.is_some());
assert_eq!(hashmap.capacity(), 16384);
assert!(hashmap.reserve(usize::MAX).is_none());
assert_eq!(hashmap.capacity(), 16384);
for i in 0..16 {
assert!(hashmap.insert(i, i).is_ok());
}
drop(reserved);
assert_eq!(hashmap.capacity(), 1024);
sourcepub fn entry(&self, key: K) -> Entry<'_, K, V, H>
pub fn entry(&self, key: K) -> Entry<'_, K, V, H>
Gets the entry associated with the given key in the map for in-place manipulation.
Examples
use scc::HashMap;
let hashmap: HashMap<char, u32> = HashMap::default();
for ch in "a short treatise on fungi".chars() {
hashmap.entry(ch).and_modify(|counter| *counter += 1).or_insert(1);
}
assert_eq!(hashmap.read(&'s', |_, v| *v), Some(2));
assert_eq!(hashmap.read(&'t', |_, v| *v), Some(3));
assert!(hashmap.read(&'y', |_, v| *v).is_none());
sourcepub async fn entry_async(&self, key: K) -> Entry<'_, K, V, H>
pub async fn entry_async(&self, key: K) -> Entry<'_, K, V, H>
Gets the entry associated with the given key in the map for in-place manipulation.
It is an asynchronous method returning an impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<char, u32> = HashMap::default();
let future_entry = hashmap.entry_async('b');
sourcepub fn first_occupied_entry(&self) -> Option<OccupiedEntry<'_, K, V, H>>
pub fn first_occupied_entry(&self) -> Option<OccupiedEntry<'_, K, V, H>>
Gets the first occupied entry for in-place manipulation.
The returned OccupiedEntry
in combination with OccupiedEntry::next
or
OccupiedEntry::next_async
can act as a mutable iterator over entries.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
let mut first_entry = hashmap.first_occupied_entry().unwrap();
*first_entry.get_mut() = 2;
assert!(first_entry.next().is_none());
assert_eq!(hashmap.read(&1, |_, v| *v), Some(2));
sourcepub async fn first_occupied_entry_async(
&self
) -> Option<OccupiedEntry<'_, K, V, H>>
pub async fn first_occupied_entry_async( &self ) -> Option<OccupiedEntry<'_, K, V, H>>
Gets the first occupied entry for in-place manipulation.
The returned OccupiedEntry
in combination with OccupiedEntry::next
or
OccupiedEntry::next_async
can act as a mutable iterator over entries.
It is an asynchronous method returning an impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<char, u32> = HashMap::default();
let future_entry = hashmap.first_occupied_entry_async();
sourcepub async fn insert_async(&self, key: K, val: V) -> Result<(), (K, V)>
pub async fn insert_async(&self, key: K, val: V) -> Result<(), (K, V)>
Inserts a key-value pair into the HashMap
.
It is an asynchronous method returning an impl Future
for the caller to await.
Errors
Returns an error along with the supplied key-value pair if the key exists.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
sourcepub fn update<Q, U, R>(&self, key: &Q, updater: U) -> Option<R>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
U: FnOnce(&K, &mut V) -> R,
pub fn update<Q, U, R>(&self, key: &Q, updater: U) -> Option<R>where K: Borrow<Q>, Q: Eq + Hash + ?Sized, U: FnOnce(&K, &mut V) -> R,
Updates an existing key-value pair.
Returns None
if the key does not exist.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.update(&1, |_, _| true).is_none());
assert!(hashmap.insert(1, 0).is_ok());
assert_eq!(hashmap.update(&1, |_, v| { *v = 2; *v }).unwrap(), 2);
assert_eq!(hashmap.read(&1, |_, v| *v).unwrap(), 2);
sourcepub async fn update_async<Q, U, R>(&self, key: &Q, updater: U) -> Option<R>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
U: FnOnce(&K, &mut V) -> R,
pub async fn update_async<Q, U, R>(&self, key: &Q, updater: U) -> Option<R>where K: Borrow<Q>, Q: Eq + Hash + ?Sized, U: FnOnce(&K, &mut V) -> R,
Updates an existing key-value pair.
Returns None
if the key does not exist. It is an asynchronous method returning an
impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
let future_update = hashmap.update_async(&1, |_, v| { *v = 2; *v });
sourcepub fn upsert<C: FnOnce() -> V, U: FnOnce(&K, &mut V)>(
&self,
key: K,
constructor: C,
updater: U
)
pub fn upsert<C: FnOnce() -> V, U: FnOnce(&K, &mut V)>( &self, key: K, constructor: C, updater: U )
Constructs the value in-place, or modifies an existing value corresponding to the key.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
hashmap.upsert(1, || 2, |_, v| *v = 2);
assert_eq!(hashmap.read(&1, |_, v| *v).unwrap(), 2);
hashmap.upsert(1, || 2, |_, v| *v = 3);
assert_eq!(hashmap.read(&1, |_, v| *v).unwrap(), 3);
sourcepub async fn upsert_async<C: FnOnce() -> V, U: FnOnce(&K, &mut V)>(
&self,
key: K,
constructor: C,
updater: U
)
pub async fn upsert_async<C: FnOnce() -> V, U: FnOnce(&K, &mut V)>( &self, key: K, constructor: C, updater: U )
Constructs the value in-place, or modifies an existing value corresponding to the key.
It is an asynchronous method returning an impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_upsert = hashmap.upsert_async(1, || 2, |_, v| *v = 3);
sourcepub fn remove<Q>(&self, key: &Q) -> Option<(K, V)>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub fn remove<Q>(&self, key: &Q) -> Option<(K, V)>where K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Removes a key-value pair if the key exists.
Returns None
if the key does not exist.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.remove(&1).is_none());
assert!(hashmap.insert(1, 0).is_ok());
assert_eq!(hashmap.remove(&1).unwrap(), (1, 0));
assert_eq!(hashmap.capacity(), 0);
sourcepub async fn remove_async<Q>(&self, key: &Q) -> Option<(K, V)>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub async fn remove_async<Q>(&self, key: &Q) -> Option<(K, V)>where K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Removes a key-value pair if the key exists.
Returns None
if the key does not exist. It is an asynchronous method returning an
impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
let future_remove = hashmap.remove_async(&11);
sourcepub fn remove_if<Q, F: FnOnce(&mut V) -> bool>(
&self,
key: &Q,
condition: F
) -> Option<(K, V)>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub fn remove_if<Q, F: FnOnce(&mut V) -> bool>( &self, key: &Q, condition: F ) -> Option<(K, V)>where K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Removes a key-value pair if the key exists and the given condition is met.
Returns None
if the key does not exist or the condition was not met.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
assert!(hashmap.remove_if(&1, |v| { *v += 1; false }).is_none());
assert_eq!(hashmap.remove_if(&1, |v| *v == 1).unwrap(), (1, 1));
assert_eq!(hashmap.capacity(), 0);
sourcepub async fn remove_if_async<Q, F: FnOnce(&mut V) -> bool>(
&self,
key: &Q,
condition: F
) -> Option<(K, V)>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub async fn remove_if_async<Q, F: FnOnce(&mut V) -> bool>( &self, key: &Q, condition: F ) -> Option<(K, V)>where K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Removes a key-value pair if the key exists and the given condition is met.
Returns None
if the key does not exist or the condition was not met. It is an
asynchronous method returning an impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
let future_remove = hashmap.remove_if_async(&11, |_| true);
sourcepub fn get<Q>(&self, key: &Q) -> Option<OccupiedEntry<'_, K, V, H>>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub fn get<Q>(&self, key: &Q) -> Option<OccupiedEntry<'_, K, V, H>>where K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Gets an occupied entry corresponding to the key.
Returns None
if the key does not exist.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.get(&1).is_none());
assert!(hashmap.insert(1, 10).is_ok());
assert_eq!(*hashmap.get(&1).unwrap().get(), 10);
sourcepub async fn get_async<Q>(&self, key: &Q) -> Option<OccupiedEntry<'_, K, V, H>>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub async fn get_async<Q>(&self, key: &Q) -> Option<OccupiedEntry<'_, K, V, H>>where K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Gets an occupied entry corresponding to the key.
Returns None
if the key does not exist. It is an asynchronous method returning an
impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
let future_get = hashmap.get_async(&11);
sourcepub fn read<Q, R, F: FnOnce(&K, &V) -> R>(
&self,
key: &Q,
reader: F
) -> Option<R>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub fn read<Q, R, F: FnOnce(&K, &V) -> R>( &self, key: &Q, reader: F ) -> Option<R>where K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Reads a key-value pair.
Returns None
if the key does not exist.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.read(&1, |_, v| *v).is_none());
assert!(hashmap.insert(1, 10).is_ok());
assert_eq!(hashmap.read(&1, |_, v| *v).unwrap(), 10);
sourcepub async fn read_async<Q, R, F: FnOnce(&K, &V) -> R>(
&self,
key: &Q,
reader: F
) -> Option<R>where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub async fn read_async<Q, R, F: FnOnce(&K, &V) -> R>( &self, key: &Q, reader: F ) -> Option<R>where K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Reads a key-value pair.
Returns None
if the key does not exist. It is an asynchronous method returning an
impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
let future_read = hashmap.read_async(&11, |_, v| *v);
sourcepub fn contains<Q>(&self, key: &Q) -> boolwhere
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub fn contains<Q>(&self, key: &Q) -> boolwhere K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Checks if the key exists.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(!hashmap.contains(&1));
assert!(hashmap.insert(1, 0).is_ok());
assert!(hashmap.contains(&1));
sourcepub async fn contains_async<Q>(&self, key: &Q) -> boolwhere
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
pub async fn contains_async<Q>(&self, key: &Q) -> boolwhere K: Borrow<Q>, Q: Eq + Hash + ?Sized,
Checks if the key exists.
It is an asynchronous method returning an impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_contains = hashmap.contains_async(&1);
sourcepub fn scan<F: FnMut(&K, &V)>(&self, scanner: F)
pub fn scan<F: FnMut(&K, &V)>(&self, scanner: F)
Scans all the entries.
Key-value pairs that have existed since the invocation of the method are guaranteed to be
visited if they are not removed, however the same key-value pair can be visited more than
once if the HashMap
gets resized by another thread.
Examples
use scc::HashMap;
let hashmap: HashMap<usize, usize> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
assert!(hashmap.insert(2, 1).is_ok());
let mut sum = 0;
hashmap.scan(|k, v| { sum += *k + *v; });
assert_eq!(sum, 4);
sourcepub async fn scan_async<F: FnMut(&K, &V)>(&self, scanner: F)
pub async fn scan_async<F: FnMut(&K, &V)>(&self, scanner: F)
Scans all the entries.
Key-value pairs that have existed since the invocation of the method are guaranteed to be
visited if they are not removed, however the same key-value pair can be visited more than
once if the HashMap
gets resized by another task.
Examples
use scc::HashMap;
let hashmap: HashMap<usize, usize> = HashMap::default();
let future_insert = hashmap.insert_async(1, 0);
let future_scan = hashmap.scan_async(|k, v| println!("{k} {v}"));
sourcepub fn any<P: FnMut(&K, &V) -> bool>(&self, pred: P) -> bool
pub fn any<P: FnMut(&K, &V) -> bool>(&self, pred: P) -> bool
Searches for any entry that satisfies the given predicate.
Key-value pairs that have existed since the invocation of the method are guaranteed to be
visited if they are not removed, however the same key-value pair can be visited more than
once if the HashMap
gets resized by another thread.
Returns true
as soon as an entry satisfying the predicate is found.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
assert!(hashmap.insert(2, 1).is_ok());
assert!(hashmap.insert(3, 2).is_ok());
assert!(hashmap.any(|k, v| *k == 1 && *v == 0));
assert!(!hashmap.any(|k, v| *k == 2 && *v == 0));
sourcepub async fn any_async<P: FnMut(&K, &V) -> bool>(&self, pred: P) -> bool
pub async fn any_async<P: FnMut(&K, &V) -> bool>(&self, pred: P) -> bool
Searches for any entry that satisfies the given predicate.
Key-value pairs that have existed since the invocation of the method are guaranteed to be
visited if they are not removed, however the same key-value pair can be visited more than
once if the HashMap
gets resized by another task.
It is an asynchronous method returning an impl Future
for the caller to await.
Returns true
as soon as an entry satisfying the predicate is found.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(1, 0);
let future_any = hashmap.any_async(|k, _| *k == 1);
sourcepub fn for_each<F: FnMut(&K, &mut V)>(&self, f: F)
pub fn for_each<F: FnMut(&K, &mut V)>(&self, f: F)
Iterates over all the entries in the HashMap
allowing modifying each value.
Key-value pairs that have existed since the invocation of the method are guaranteed to be
visited if they are not removed, however the same key-value pair can be visited more than
once if the HashMap
gets resized by another thread.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
assert!(hashmap.insert(2, 1).is_ok());
let mut acc = 0;
hashmap.for_each(|k, v| { acc += *k; *v = 2; });
assert_eq!(acc, 3);
assert_eq!(hashmap.read(&1, |_, v| *v).unwrap(), 2);
assert_eq!(hashmap.read(&2, |_, v| *v).unwrap(), 2);
sourcepub async fn for_each_async<F: FnMut(&K, &mut V)>(&self, f: F)
pub async fn for_each_async<F: FnMut(&K, &mut V)>(&self, f: F)
Iterates over all the entries in the HashMap
allowing modifying each value.
Key-value pairs that have existed since the invocation of the method are guaranteed to be
visited if they are not removed, however the same key-value pair can be visited more than
once if the HashMap
gets resized by another task.
It is an asynchronous method returning an impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(1, 0);
let future_for_each = hashmap.for_each_async(|k, v| println!("{} {}", k, v));
sourcepub fn retain<F: FnMut(&K, &mut V) -> bool>(&self, pred: F) -> (usize, usize)
pub fn retain<F: FnMut(&K, &mut V) -> bool>(&self, pred: F) -> (usize, usize)
Retains the entries specified by the predicate.
This method allows the predicate closure to modify the value field.
Entries that have existed since the invocation of the method are guaranteed to be visited
if they are not removed, however the same entry can be visited more than once if the
HashMap
gets resized by another thread.
Returns (number of remaining entries, number of removed entries)
where the number of
remaining entries can be larger than the actual number since the same entry can be visited
more than once.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
assert!(hashmap.insert(2, 1).is_ok());
assert!(hashmap.insert(3, 2).is_ok());
assert_eq!(hashmap.retain(|k, v| *k == 1 && *v == 0), (1, 2));
sourcepub async fn retain_async<F: FnMut(&K, &mut V) -> bool>(
&self,
pred: F
) -> (usize, usize)
pub async fn retain_async<F: FnMut(&K, &mut V) -> bool>( &self, pred: F ) -> (usize, usize)
Retains the entries specified by the predicate.
This method allows the predicate closure to modify the value field.
Entries that have existed since the invocation of the method are guaranteed to be visited
if they are not removed, however the same entry can be visited more than once if the
HashMap
gets resized by another thread.
Returns (number of remaining entries, number of removed entries)
where the number of
remaining entries can be larger than the actual number since the same entry can be visited
more than once. It is an asynchronous method returning an impl Future
for the caller to
await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(1, 0);
let future_retain = hashmap.retain_async(|k, v| *k == 1);
sourcepub fn prune<F: FnMut(&K, V) -> Option<V>>(&self, pred: F) -> usize
pub fn prune<F: FnMut(&K, V) -> Option<V>>(&self, pred: F) -> usize
Prunes the entries specified by the predicate, and returns the number of removed entries.
If the value is consumed by the predicate, in other words, if the predicate returns None
,
the entry is removed, otherwise the entry is retained.
Entries that have existed since the invocation of the method are guaranteed to be visited
if they are not removed, however the same entry can be visited more than once if the
HashMap
gets resized by another thread.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
assert!(hashmap.insert(2, 1).is_ok());
assert!(hashmap.insert(3, 2).is_ok());
assert_eq!(hashmap.prune(|k, v| if *k == 1 { Some(v) } else { None }), 2);
assert_eq!(hashmap.len(), 1);
sourcepub async fn prune_async<F: FnMut(&K, V) -> Option<V>>(&self, pred: F) -> usize
pub async fn prune_async<F: FnMut(&K, V) -> Option<V>>(&self, pred: F) -> usize
Prunes the entries specified by the predicate, and returns the number of removed entries.
If the value is consumed by the predicate, in other words, if the predicate returns None
,
the entry is removed, otherwise the entry is retained.
Entries that have existed since the invocation of the method are guaranteed to be visited
if they are not removed, however the same entry can be visited more than once if the
HashMap
gets resized by another thread.
It is an asynchronous method returning an impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(1, 0);
let future_prune = hashmap.prune_async(|k, v| if *k == 1 { Some(v) } else { None });
sourcepub fn clear(&self) -> usize
pub fn clear(&self) -> usize
Clears all the key-value pairs.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
assert_eq!(hashmap.clear(), 1);
sourcepub async fn clear_async(&self) -> usize
pub async fn clear_async(&self) -> usize
Clears all the key-value pairs.
It is an asynchronous method returning an impl Future
for the caller to await.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(1, 0);
let future_clear = hashmap.clear_async();
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of entries in the HashMap
.
It reads the entire metadata area of the bucket array to calculate the number of valid
entries, making its time complexity O(N)
. Furthermore, it may overcount entries if an old
bucket array has yet to be dropped.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert(1, 0).is_ok());
assert_eq!(hashmap.len(), 1);
sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the capacity of the HashMap
.
Examples
use scc::HashMap;
let hashmap_default: HashMap<u64, u32> = HashMap::default();
assert_eq!(hashmap_default.capacity(), 0);
assert!(hashmap_default.insert(1, 0).is_ok());
assert_eq!(hashmap_default.capacity(), 64);
let hashmap: HashMap<u64, u32> = HashMap::with_capacity(1000000);
assert_eq!(hashmap.capacity(), 1048576);
sourcepub fn capacity_range(&self) -> RangeInclusive<usize>
pub fn capacity_range(&self) -> RangeInclusive<usize>
Returns the current capacity range of the HashMap
.
Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert_eq!(hashmap.capacity_range(), 0..=(1_usize << (usize::BITS - 1)));
let reserved = hashmap.reserve(1000);
assert_eq!(hashmap.capacity_range(), 1000..=(1_usize << (usize::BITS - 1)));
Trait Implementations§
source§impl<'h, K, V, H> AsRef<HashMap<K, V, H>> for Reserve<'h, K, V, H>where
K: Eq + Hash,
H: BuildHasher,
impl<'h, K, V, H> AsRef<HashMap<K, V, H>> for Reserve<'h, K, V, H>where K: Eq + Hash, H: BuildHasher,
source§impl<K, V, H> Clone for HashMap<K, V, H>where
K: Clone + Eq + Hash,
V: Clone,
H: BuildHasher + Clone,
impl<K, V, H> Clone for HashMap<K, V, H>where K: Clone + Eq + Hash, V: Clone, H: BuildHasher + Clone,
source§impl<K, V, H> Debug for HashMap<K, V, H>where
K: Debug + Eq + Hash,
V: Debug,
H: BuildHasher,
impl<K, V, H> Debug for HashMap<K, V, H>where K: Debug + Eq + Hash, V: Debug, H: BuildHasher,
source§fn fmt(&self, f: &mut Formatter<'_>) -> Result
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Iterates over all the entries in the HashMap
to print them.
Locking behavior
Shared locks on buckets are acquired during iteration, therefore any Entry
,
OccupiedEntry
or VacantEntry
owned by the current thread will lead to a deadlock.