pub struct HashMap<K, V, H = RandomState> where
    K: 'static + Eq + Hash + Sync,
    V: 'static + Sync,
    H: BuildHasher
{ /* private fields */ }
Expand description

Scalable concurrent hash map.

HashMap is a concurrent hash map data structure that is targeted at a highly concurrent workload. The use of an epoch-based reclamation technique enables the data structure to implement non-blocking resizing and fine-granular locking. A HashMap instance only has a single array of entries instead of a fixed number of lock-protected hash tables. An entry of the array is called a Cell; it manages a fixed number of key-value pairs using a customized mutex in it, and resolves hash conflicts by allocating a linked list of smaller hash tables.

The key features of HashMap

  • Non-sharded: the data is stored in a single array of key-value pairs.
  • Non-blocking resizing: resizing does not block other threads or tasks.
  • Automatic resizing: it automatically grows or shrinks.
  • Incremental resizing: each access to the data structure is mandated to rehash a fixed number of key-value pairs.
  • Optimized resizing: key-value pairs managed by a single Cell are guaranteed to be relocated to consecutive Cell instances.
  • No busy waiting: the customized mutex never spins.
  • Linearlizability: HashMap methods are linearlizable.

The key statistics for HashMap

  • The expected size of metadata for a single key-value pair: 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 metadata Cell without a linked list: 32.
  • The expected maximum linked list length when resize is triggered: log(capacity) / 8.

Implementations

Creates an empty HashMap with the given capacity and BuildHasher.

The actual capacity is equal to or greater than the given capacity.

Examples
use scc::HashMap;
use std::collections::hash_map::RandomState;

let hashmap: HashMap<u64, u32, RandomState> = HashMap::new(1000, RandomState::new());

let result = hashmap.capacity();
assert_eq!(result, 1024);

let hashmap: HashMap<u64, u32> = HashMap::default();
let result = hashmap.capacity();
assert_eq!(result, 64);

Temporarily increases the minimum capacity of the HashMap.

The reserved space is not exclusively owned by the Ticket, thus can be overtaken. Unused space is immediately reclaimed when the Ticket is dropped.

Errors

Returns None if a too large number is given.

Examples
use scc::HashMap;
use std::collections::hash_map::RandomState;

let hashmap: HashMap<usize, usize, RandomState> = HashMap::new(1000, RandomState::new());
assert_eq!(hashmap.capacity(), 1024);

let ticket = hashmap.reserve(10000);
assert!(ticket.is_some());
assert_eq!(hashmap.capacity(), 16384);
for i in 0..16 {
    assert!(hashmap.insert(i, i).is_ok());
}
drop(ticket);

assert_eq!(hashmap.capacity(), 1024);

Inserts a key-value pair into the HashMap.

Errors

Returns an error along with the supplied key-value pair if the key exists.

Panics

Panics if memory allocation fails, or the number of entries in the target cell reaches u32::MAX.

Examples
use scc::HashMap;

let hashmap: HashMap<u64, u32> = HashMap::default();

assert!(hashmap.insert(1, 0).is_ok());
assert_eq!(hashmap.insert(1, 1).unwrap_err(), (1, 1));

Inserts a key-value pair into the HashMap.

It is an asynchronous method returning an impl Future for the caller to await or poll.

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);

Updates an existing key-value pair.

It 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);

Updates an existing key-value pair.

It returns None if the key does not exist. It is an asynchronous method returning an impl Future for the caller to await or poll.

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 });

Constructs the value in-place, or modifies an existing value corresponding to the key.

Panics

Panics if memory allocation fails, or the number of entries in the target cell is reached u32::MAX.

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);

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 or poll.

Panics

Panics if memory allocation fails, or the number of entries in the target cell is reached u32::MAX.

Examples
use scc::HashMap;

let hashmap: HashMap<u64, u32> = HashMap::default();

let future_upsert = hashmap.upsert_async(1, || 2, |_, v| *v = 3);

Removes a key-value pair if the key exists.

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));

Removes a key-value pair if the key exists.

It is an asynchronous method returning an impl Future for the caller to await or poll.

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);

Removes a key-value pair if the key exists and the given condition is 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).is_none());
assert_eq!(hashmap.remove_if(&1, |v| *v == 0).unwrap(), (1, 0));

Removes a key-value pair if the key exists and the given condition is met.

It is an asynchronous method returning an impl Future for the caller to await or poll.

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);

Reads a key-value pair.

It 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);

Reads a key-value pair.

It returns None if the key does not exist. It is an asynchronous method returning an impl Future for the caller to await or poll.

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);

Reads a key-value pair using the supplied Barrier.

It enables the caller to use the value reference outside the method. It returns None if the key does not exist.

Examples
use scc::ebr::Barrier;
use scc::HashMap;

let hashmap: HashMap<u64, u32> = HashMap::default();

assert!(hashmap.insert(1, 10).is_ok());

let barrier = Barrier::new();
let value_ref = hashmap.read_with(&1, |k, v| v, &barrier).unwrap();
assert_eq!(*value_ref, 10);

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));

Checks if the key exists.

It is an asynchronous method returning an impl Future for the caller to await or poll.

Examples
use scc::HashMap;

let hashmap: HashMap<u64, u32> = HashMap::default();

let future_contains = hashmap.contains_async(&1);

Scans all the key-value pairs.

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);

Scans all the key-value pairs.

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_retain = hashmap.scan_async(|k, v| println!("{k} {v}"));

Iterates over all the entries in the HashMap.

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);

Iterates over all the entries in the HashMap.

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 or poll.

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));

Retains key-value pairs that satisfy 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.

It returns the number of entries remaining and removed.

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));

Retains key-value pairs that satisfy 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 returns the number of entries remaining and removed. It is an asynchronous method returning an impl Future for the caller to await or poll.

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);

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);

Clears all the key-value pairs.

It is an asynchronous method returning an impl Future for the caller to await or poll.

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();

Returns the number of entries in the HashMap.

It scans the entire array to calculate the number of valid entries, making its time complexity O(N).

Examples
use scc::HashMap;

let hashmap: HashMap<u64, u32> = HashMap::default();

assert!(hashmap.insert(1, 0).is_ok());
assert_eq!(hashmap.len(), 1);

Returns true if the HashMap is empty.

It scans the entire array to calculate the number of valid entries, making its time complexity O(N).

Examples
use scc::HashMap;

let hashmap: HashMap<u64, u32> = HashMap::default();

assert!(hashmap.is_empty());

Returns the capacity of the HashMap.

Examples
use scc::HashMap;
use std::collections::hash_map::RandomState;

let hashmap: HashMap<u64, u32, RandomState> = HashMap::new(1000000, RandomState::new());
assert_eq!(hashmap.capacity(), 1048576);

Trait Implementations

Creates a HashMap with the default parameters.

The default hash builder is RandomState, and the default capacity is 64.

Examples
use scc::HashMap;

let hashmap: HashMap<u64, u32> = HashMap::default();

let result = hashmap.capacity();
assert_eq!(result, 64);

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.