pub struct AtomicMap<K: Eq + Hash>(/* private fields */);Expand description
Like Map, AtomicMap provides simple, fast sequence checking by key, but with
the thread-safe backing storage of AtomicIncr.
§Tradeoffs
AtomicMap is not a concurrent hashmap. Importantly key insertion is not
synchronized. The intended use case is to initialize the map fully on program start,
inserting whatever keys will be used throughout its life, and cloning this master
instance to be used by any threads tracking sequences by those keys.
A fully synchronized map was not chosen for performance reasons. If keys are not fully known when threads are launched, the best options include:
- wrap a normal
Mapin anArc<Mutex<Map>>orArc<RwLock<Map>>, - utilize a third-party crate providing a concurrent hashmap implementation
(with
Incrvalues).
For a given (already inserted) key, any clone()d AtomicMap will use/have a
value at that key that is synchronized across threads (the inner value is
an Arc<AtomicU64>).
§Examples
use incr::AtomicMap;
let mut last: AtomicMap<&'static str> = Default::default();
assert_eq!(last.insert("a", 1), true);
assert_eq!(last.is_new("missing_key", 1), false); // note difference from `Map`
assert_eq!(last.insert("b", 1), true);
assert_eq!(last.is_new("a", 1), false);
assert_eq!(last.is_new("b", 3), true);
assert_eq!(last.is_new_or_insert("c", 1), true);
assert_eq!(last.is_new("c", 1), false);
assert_eq!(last.get("b"), 3);
assert_eq!(last.get("not a key"), 0);Implementations§
Source§impl<K> AtomicMap<K>
impl<K> AtomicMap<K>
Sourcepub fn is_new<Q>(&self, key: &Q, val: u64) -> bool
pub fn is_new<Q>(&self, key: &Q, val: u64) -> bool
Returns true if key exists and val is greater than the largest
previously observed value (for key). Returns false if key does
not exist in the inner map. See AtomicMap::check_or_insert for a function
that behaves similarly to Map::is_new.
§Tradeoffs
This function has a different signature and works differently than
Map::is_new.
Specifically, Map::is_new:
- takes
&mut self - consumes
key - inserts
valatkeyifkeywas not already present in the map.
By contrast, AtomicIncr:
- takes
&self - borrows
&key - does not insert
valon a key miss, instead “silently” returningfalse
This design was chosen for several reasons, including:
- key insertions are not synchronized across threads. Instead, the map is expected to have been initialized on program start, and a key miss is most likely an error
- A
&selfsignature provides more flexibility, and is possible, unlike withMap, because theAtomicIncr::is_newfunction takes&self
The AtomicMap::check_or_insert function provides insert-on-key-miss
functionality if desired.
Possibly, it would be less confusing if this function returned Option<bool>,
where a key miss would return None. Feedback on this issue would be
appreciated.
§Examples
use incr::AtomicMap;
let mut last: AtomicMap<&'static str> = Default::default();
assert_eq!(last.is_new("a", 1), false);
assert_eq!(last.contains_key("a"), false);
assert_eq!(last.is_new_or_insert("a", 1), true);
assert_eq!(last.get("a"), 1);
assert_eq!(last.insert("b", 1), true);
assert_eq!(last.is_new("b", 2), true);
assert_eq!(last.is_new("b", 2), false);Sourcepub fn is_new_or_insert(&mut self, key: K, val: u64) -> bool
pub fn is_new_or_insert(&mut self, key: K, val: u64) -> bool
Like is_new, but inserts val at key if the inner map did not
previously contain key.
This may be renamed to check_or_insert in the future.
Sourcepub fn insert(&mut self, key: K, val: u64) -> bool
pub fn insert(&mut self, key: K, val: u64) -> bool
An alias for, and Works identically to, is_new_or_insert. It’s
not possible, using the public api, to decrease the value at a given
key, so calling this with a val lower than the current value
would simply return false and leave the higher value in the map
unchanged.
Sourcepub fn get<Q>(&self, key: &Q) -> u64
pub fn get<Q>(&self, key: &Q) -> u64
Returns the highest observed value at key, or, if key does not exist,
returns 0.