Module sync42::state_hash_table
source · Expand description
StateHashTable solves the rendezvous problem.
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use sync42::state_hash_table::{Handle, Key, Value, StateHashTable};
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
struct SampleKey {
key: u64,
}
impl SampleKey {
const fn new(key: u64) -> Self {
Self {
key,
}
}
}
impl Key for SampleKey {
}
#[derive(Debug, Default)]
struct SampleValue {
finished: AtomicBool,
}
impl From<SampleKey> for SampleValue {
fn from(key: SampleKey) -> Self {
Self {
finished: AtomicBool::default(),
}
}
}
impl Value for SampleValue {
fn finished(&self) -> bool { self.finished.load(Ordering::Relaxed) }
}
// Create the state hash table. This should be a global-ish structure.
let mut sht: StateHashTable<SampleKey, SampleValue> = StateHashTable::new();
// Everything revolves around the key. We don't demonstrate this, but different keys are
// totally partitioned and do not interact except to contend on a shared lock.
const KEY: SampleKey = SampleKey::new(42);
// There's nothing there until we create it.
assert!(sht.get_state(KEY).is_none());
let mut state1 = sht.create_state(KEY);
assert!(state1.is_some());
let mut state1 = state1.unwrap();
// Attempts to create twice fail with None.
let mut state2 = sht.create_state(KEY);
assert!(state2.is_none());
// But get_state will work.
let mut state3 = sht.get_state(KEY);
assert!(state3.is_some());
let mut state3 = state3.unwrap();
// It is guaranteed that when two threads hold reference to the same hash table and have [Eq]
// keys they will be the same underlying value.
Handle::is_same(&state1, &state3);
// It is also guaranteed that when state is dropped but the work is unfinished that the value
// will persist in the table. Note that there will be no handles to this state and it will
// persist.
drop(state1);
drop(state3);
// Notice that we use [get_state] here. It uses the existing state.
let mut state4 = sht.get_state(KEY);
assert!(state4.is_some());
let mut state4 = state4.unwrap();
state4.finished.store(true, Ordering::Relaxed);
// Drop the remaining references.
drop(state4);
// Get state fails because we marked it finished and dropped all references. Only when the
// last reference is dropped will the item be collected, even if the outcome of the
// [finished()] call changes.
let mut state5 = sht.get_state(KEY);
assert!(state5.is_none());
Structs§
- A Handle holds a reference to a key-value pair in a table. Two handles that come from the same table and key are guaranteed to refer to the same piece of state.
- StateHashTable is the main collection.
Traits§
- A key for a state hash table.
- A value for a state hash table.
Functions§
- Register the biometrics for state hash table.