Skip to content

Add read-only query APIs for find, probe_value, and unioned for Concurrency #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions src/unify/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,13 +374,32 @@ impl<S: UnificationStoreMut> UnificationTable<S> {
root_key
}

/// read-only version of `inlined_get_root_key`
#[inline(always)]
fn read_inlined_get_root_key(&self, vid: S::Key) -> S::Key {
let redirect = {
match self.value(vid).parent(vid) {
None => return vid,
Some(redirect) => redirect,
}
};

self.read_uninlined_get_root_key(redirect)
}

// This is a never-inlined version of this function for cold callsites.
// 'inlined_get_root_key` is the always-inlined version.
#[inline(never)]
fn uninlined_get_root_key(&mut self, vid: S::Key) -> S::Key {
self.inlined_get_root_key(vid)
}

// read-only version of `uninlined_get_root_key`, no path-compression
#[inline(never)]
fn read_uninlined_get_root_key(&self, vid: S::Key) -> S::Key {
self.read_inlined_get_root_key(vid)
}

fn update_value<OP>(&mut self, key: S::Key, op: OP)
where
OP: FnOnce(&mut VarValue<S::Key>),
Expand Down Expand Up @@ -502,6 +521,15 @@ where
self.find(a_id) == self.find(b_id)
}

/// read-only version of `unioned`, no path-compression
pub fn read_unioned<K1, K2>(&self, a_id: K1, b_id: K2) -> bool
where
K1: Into<K>,
K2: Into<K>,
{
self.read_find(a_id) == self.read_find(b_id)
}

/// Given a key, returns the (current) root key.
pub fn find<K1>(&mut self, id: K1) -> K
where
Expand All @@ -511,6 +539,15 @@ where
self.uninlined_get_root_key(id)
}

/// Given a key, returns the (current) root key, no path compression
pub fn read_find<K1>(&self, id: K1) -> K
where
K1: Into<K>,
{
let id = id.into();
self.read_uninlined_get_root_key(id)
}

/// Unions together two variables, merging their values. If
/// merging the values fails, the error is propagated and this
/// method has no effect.
Expand Down Expand Up @@ -556,6 +593,14 @@ where
self.inlined_probe_value(id)
}

// read-only version, allowing concurrency
pub fn read_probe_value<K1>(&self, id: K1) -> V
where
K1: Into<K>,
{
self.read_inlined_probe_value(id)
}

// An always-inlined version of `probe_value`, for hot callsites.
#[inline(always)]
pub fn inlined_probe_value<K1>(&mut self, id: K1) -> V
Expand All @@ -566,6 +611,17 @@ where
let id = self.inlined_get_root_key(id);
self.value(id).value.clone()
}

// An always-inlined version of `probe_value`, for hot callsites.
#[inline(always)]
pub fn read_inlined_probe_value<K1>(&self, id: K1) -> V
where
K1: Into<K>,
{
let id = id.into();
let id = self.read_inlined_get_root_key(id);
self.value(id).value.clone()
}
}

///////////////////////////////////////////////////////////////////////////
Expand Down
14 changes: 14 additions & 0 deletions src/unify/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ fn basic() {
let k1 = ut.new_key(());
let k2 = ut.new_key(());
assert_eq!(ut.unioned(k1, k2), false);
assert_eq!(ut.read_unioned(k1, k2), false);
ut.union(k1, k2);
assert_eq!(ut.unioned(k1, k2), true);
assert_eq!(ut.read_unioned(k1, k2), true);
}
}
}
Expand All @@ -87,6 +89,7 @@ fn big_array() {

for i in 0..MAX {
assert!(ut.unioned(keys[0], keys[i]));
assert!(ut.read_unioned(keys[0], keys[i]));
}
}
}
Expand Down Expand Up @@ -232,10 +235,12 @@ fn even_odd() {

for i in 1..MAX {
assert!(!ut.unioned(keys[i - 1], keys[i]));
assert!(!ut.read_unioned(keys[i - 1], keys[i]));
}

for i in 2..MAX {
assert!(ut.unioned(keys[i - 2], keys[i]));
assert!(!ut.read_unioned(keys[i - 1], keys[i]));
}
}
}
Expand Down Expand Up @@ -270,6 +275,7 @@ fn unify_same_int_twice() {
assert!(ut.unify_var_value(k2, Some(22)).is_ok());
assert!(ut.unify_var_var(k1, k2).is_ok());
assert_eq!(ut.probe_value(k1), Some(22));
assert_eq!(ut.read_probe_value(k1), Some(22));
}
}
}
Expand All @@ -284,6 +290,7 @@ fn unify_vars_then_int_indirect() {
assert!(ut.unify_var_var(k1, k2).is_ok());
assert!(ut.unify_var_value(k1, Some(22)).is_ok());
assert_eq!(ut.probe_value(k2), Some(22));
assert_eq!(ut.read_probe_value(k1), Some(22));
}
}
}
Expand Down Expand Up @@ -425,6 +432,7 @@ fn ordered_key() {

ut.union(k0_1, k0_5); // new root rank 2, should not be k0_5 or k0_6
assert!(vec![k0_1, k0_2, k0_3, k0_4].contains(&ut.find(k0_1)));
assert!(vec![k0_1, k0_2, k0_3, k0_4].contains(&ut.read_find(k0_1)));
}
}
}
Expand Down Expand Up @@ -471,16 +479,22 @@ fn clone_table() {
assert!(ut.unify_var_value(k2, Some(22)).is_ok());
assert!(ut.unify_var_var(k1, k2).is_ok());
assert_eq!(ut.probe_value(k3), None);
assert_eq!(ut.read_probe_value(k3), None);

let mut ut1 = ut.clone();
assert_eq!(ut1.probe_value(k1), Some(22));
assert_eq!(ut1.read_probe_value(k1), Some(22));
assert_eq!(ut1.probe_value(k3), None);
assert_eq!(ut1.read_probe_value(k3), None);

assert!(ut.unify_var_value(k3, Some(44)).is_ok());

assert_eq!(ut1.probe_value(k1), Some(22));
assert_eq!(ut1.read_probe_value(k1), Some(22));
assert_eq!(ut1.probe_value(k3), None);
assert_eq!(ut1.read_probe_value(k3), None);
assert_eq!(ut.probe_value(k3), Some(44));
assert_eq!(ut.read_probe_value(k3), Some(44));
}
}
}