Part 2: Use ValueRc in InternSet.

We haven't observed performance issues using `Arc` instead of `Rc`,
and we want to be able to include things that are interned (including,
soon, `TempId` instances) in errors coming out of the
transactor.  (And `Rc` isn't `Sync`, so it can't be included in errors
directly.)
This commit is contained in:
Nick Alexander 2018-07-02 09:34:57 -07:00
parent 87f850a44e
commit 02a163a10f
3 changed files with 21 additions and 21 deletions

View file

@ -17,7 +17,6 @@ use std::collections::{
BTreeSet, BTreeSet,
HashMap, HashMap,
}; };
use std::rc::Rc;
use mentat_core::KnownEntid; use mentat_core::KnownEntid;
@ -27,6 +26,14 @@ use edn;
use edn::{ use edn::{
SpannedValue, SpannedValue,
ValueAndSpan, ValueAndSpan,
ValueRc,
};
use edn::entities;
use edn::entities::{
EntityPlace,
OpType,
TempId,
TxFunction,
}; };
use errors; use errors;
@ -47,13 +54,6 @@ use types::{
TypedValue, TypedValue,
ValueType, ValueType,
}; };
use edn::entities;
use edn::entities::{
EntityPlace,
OpType,
TempId,
TxFunction,
};
impl TransactableValue for ValueAndSpan { impl TransactableValue for ValueAndSpan {
fn into_typed_value(self, schema: &Schema, value_type: ValueType) -> Result<TypedValue> { fn into_typed_value(self, schema: &Schema, value_type: ValueType) -> Result<TypedValue> {
@ -150,10 +150,10 @@ use self::Either::*;
pub type KnownEntidOr<T> = Either<KnownEntid, T>; pub type KnownEntidOr<T> = Either<KnownEntid, T>;
pub type TypedValueOr<T> = Either<TypedValue, T>; pub type TypedValueOr<T> = Either<TypedValue, T>;
pub type TempIdHandle = Rc<TempId>; pub type TempIdHandle = ValueRc<TempId>;
pub type TempIdMap = HashMap<TempIdHandle, KnownEntid>; pub type TempIdMap = HashMap<TempIdHandle, KnownEntid>;
pub type LookupRef = Rc<AVPair>; pub type LookupRef = ValueRc<AVPair>;
/// Internal representation of an entid on its way to resolution. We either have the simple case (a /// Internal representation of an entid on its way to resolution. We either have the simple case (a
/// numeric entid), a lookup-ref that still needs to be resolved (an atomized [a v] pair), or a temp /// numeric entid), a lookup-ref that still needs to be resolved (an atomized [a v] pair), or a temp

View file

@ -56,9 +56,6 @@ use std::collections::{
use std::iter::{ use std::iter::{
once, once,
}; };
use std::rc::{
Rc,
};
use db; use db;
use db::{ use db::{
@ -68,6 +65,7 @@ use db::{
use edn::{ use edn::{
InternSet, InternSet,
Keyword, Keyword,
ValueRc,
}; };
use entids; use entids;
use errors; use errors;
@ -303,7 +301,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
Ok(self.lookup_refs.intern((lr_a, lr_typed_value))) Ok(self.lookup_refs.intern((lr_a, lr_typed_value)))
} }
fn intern_temp_id(&mut self, temp_id: TempId) -> Rc<TempId> { fn intern_temp_id(&mut self, temp_id: TempId) -> ValueRc<TempId> {
self.temp_ids.intern(temp_id) self.temp_ids.intern(temp_id)
} }

View file

@ -12,7 +12,10 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::hash::Hash; use std::hash::Hash;
use std::rc::Rc;
use ::{
ValueRc,
};
/// An `InternSet` allows to "intern" some potentially large values, maintaining a single value /// An `InternSet` allows to "intern" some potentially large values, maintaining a single value
/// instance owned by the `InternSet` and leaving consumers with lightweight ref-counted handles to /// instance owned by the `InternSet` and leaving consumers with lightweight ref-counted handles to
@ -23,7 +26,7 @@ use std::rc::Rc;
/// See https://en.wikipedia.org/wiki/String_interning for discussion. /// See https://en.wikipedia.org/wiki/String_interning for discussion.
#[derive(Clone, Debug, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct InternSet<T> where T: Eq + Hash { pub struct InternSet<T> where T: Eq + Hash {
pub inner: HashSet<Rc<T>>, pub inner: HashSet<ValueRc<T>>,
} }
impl<T> InternSet<T> where T: Eq + Hash { impl<T> InternSet<T> where T: Eq + Hash {
@ -40,13 +43,12 @@ impl<T> InternSet<T> where T: Eq + Hash {
/// Intern a value, providing a ref-counted handle to the interned value. /// Intern a value, providing a ref-counted handle to the interned value.
/// ///
/// ``` /// ```
/// use std::rc::Rc; /// use edn::{InternSet, ValueRc};
/// use edn::intern_set::InternSet;
/// ///
/// let mut s = InternSet::new(); /// let mut s = InternSet::new();
/// ///
/// let one = "foo".to_string(); /// let one = "foo".to_string();
/// let two = Rc::new("foo".to_string()); /// let two = ValueRc::new("foo".to_string());
/// ///
/// let out_one = s.intern(one); /// let out_one = s.intern(one);
/// assert_eq!(out_one, two); /// assert_eq!(out_one, two);
@ -57,8 +59,8 @@ impl<T> InternSet<T> where T: Eq + Hash {
/// assert_eq!(1, s.inner.len()); /// assert_eq!(1, s.inner.len());
/// // assert!(&out_one.ptr_eq(&out_two)); // Nightly-only. /// // assert!(&out_one.ptr_eq(&out_two)); // Nightly-only.
/// ``` /// ```
pub fn intern<R: Into<Rc<T>>>(&mut self, value: R) -> Rc<T> { pub fn intern<R: Into<ValueRc<T>>>(&mut self, value: R) -> ValueRc<T> {
let key: Rc<T> = value.into(); let key: ValueRc<T> = value.into();
if self.inner.insert(key.clone()) { if self.inner.insert(key.clone()) {
key key
} else { } else {