diff --git a/src/unify/mod.rs b/src/unify/mod.rs index a26d699..8a1e234 100644 --- a/src/unify/mod.rs +++ b/src/unify/mod.rs @@ -374,6 +374,19 @@ impl UnificationTable { 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)] @@ -381,6 +394,12 @@ impl UnificationTable { 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(&mut self, key: S::Key, op: OP) where OP: FnOnce(&mut VarValue), @@ -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(&self, a_id: K1, b_id: K2) -> bool + where + K1: Into, + K2: Into, + { + self.read_find(a_id) == self.read_find(b_id) + } + /// Given a key, returns the (current) root key. pub fn find(&mut self, id: K1) -> K where @@ -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(&self, id: K1) -> K + where + K1: Into, + { + 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. @@ -556,6 +593,14 @@ where self.inlined_probe_value(id) } + // read-only version, allowing concurrency + pub fn read_probe_value(&self, id: K1) -> V + where + K1: Into, + { + self.read_inlined_probe_value(id) + } + // An always-inlined version of `probe_value`, for hot callsites. #[inline(always)] pub fn inlined_probe_value(&mut self, id: K1) -> V @@ -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(&self, id: K1) -> V + where + K1: Into, + { + let id = id.into(); + let id = self.read_inlined_get_root_key(id); + self.value(id).value.clone() + } } /////////////////////////////////////////////////////////////////////////// diff --git a/src/unify/tests.rs b/src/unify/tests.rs index 5665aba..949be61 100644 --- a/src/unify/tests.rs +++ b/src/unify/tests.rs @@ -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); } } } @@ -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])); } } } @@ -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])); } } } @@ -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)); } } } @@ -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)); } } } @@ -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))); } } } @@ -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)); } } }