Skip to content

Commit

Permalink
Merge pull request #78 from GarkGarcia/master
Browse files Browse the repository at this point in the history
Finish fixing #17
  • Loading branch information
jonhoo authored Mar 27, 2020
2 parents 5f8e123 + ba9f527 commit d1f67c2
Show file tree
Hide file tree
Showing 4 changed files with 415 additions and 25 deletions.
20 changes: 20 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,19 +213,23 @@
intra_doc_link_resolution_failure
)]
#![warn(rust_2018_idioms)]
use crossbeam_epoch::Guard;
use std::ops::Deref;

mod map;
mod map_ref;
mod node;
mod raw;
mod set;
mod set_ref;

/// Iterator types.
pub mod iter;

pub use map::{HashMap, TryInsertError};
pub use map_ref::HashMapRef;
pub use set::HashSet;
pub use set_ref::HashSetRef;

/// Default hasher for [`HashMap`].
pub type DefaultHashBuilder = ahash::RandomState;
Expand All @@ -234,3 +238,19 @@ pub type DefaultHashBuilder = ahash::RandomState;
pub mod epoch {
pub use crossbeam_epoch::{pin, Guard};
}

pub(crate) enum GuardRef<'g> {
Owned(Guard),
Ref(&'g Guard),
}

impl Deref for GuardRef<'_> {
type Target = Guard;

#[inline]
fn deref(&self) -> &Guard {
match *self {
GuardRef::Owned(ref guard) | GuardRef::Ref(&ref guard) => guard,
}
}
}
20 changes: 2 additions & 18 deletions src/map_ref.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::iter::*;
use crate::{HashMap, TryInsertError};
use crate::{GuardRef, HashMap, TryInsertError};
use crossbeam_epoch::Guard;
use std::borrow::Borrow;
use std::fmt::{self, Debug, Formatter};
use std::hash::{BuildHasher, Hash};
use std::ops::{Deref, Index};
use std::ops::Index;

/// A reference to a [`HashMap`], constructed with [`HashMap::pin`] or [`HashMap::with_guard`].
///
Expand All @@ -15,22 +15,6 @@ pub struct HashMapRef<'map, K, V, S = crate::DefaultHashBuilder> {
guard: GuardRef<'map>,
}

enum GuardRef<'g> {
Owned(Guard),
Ref(&'g Guard),
}

impl Deref for GuardRef<'_> {
type Target = Guard;

#[inline]
fn deref(&self) -> &Guard {
match *self {
GuardRef::Owned(ref guard) | GuardRef::Ref(&ref guard) => guard,
}
}
}

impl<K, V, S> HashMap<K, V, S> {
/// Get a reference to this map with the current thread pinned.
///
Expand Down
163 changes: 156 additions & 7 deletions src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl<T, S> HashSet<T, S> {
self.map.guard()
}

/// Returns the number of entries in the set.
/// Returns the number of elements in the set.
///
/// # Examples
///
Expand Down Expand Up @@ -190,9 +190,9 @@ impl<T, S> HashSet<T, S> {
self.len() == 0
}

/// An iterator visiting all values in arbitrary order.
/// An iterator visiting all elements in arbitrary order.
///
/// The iterator element type is `(&'g K, &'g V)`.
/// The iterator element type is `&'g T`.
///
/// See [`HashMap::keys`] for details.
///
Expand Down Expand Up @@ -220,7 +220,7 @@ where
T: Hash + Eq,
S: BuildHasher,
{
/// Returns `true` if the set contains the specified value.
/// Returns `true` if the given value is an element of this set.
///
/// The value may be any borrowed form of the set's value type, but
/// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
Expand Down Expand Up @@ -250,7 +250,7 @@ where
self.map.contains_key(value, guard)
}

/// Returns a reference to the value in the set, if any, that is equal to the given value.
/// Returns a reference to the element in the set, if any, that is equal to the given value.
///
/// The value may be any borrowed form of the set's value type, but
/// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
Expand All @@ -276,6 +276,101 @@ where
{
self.map.get_key_value(value, guard).map(|(k, _)| k)
}

/// Returns `true` if `self` has no elements in common with `other`.
///
/// This is equivalent to checking for an empty intersection.
///
/// # Examples
///
/// ```
/// use std::iter::FromIterator;
/// use flurry::HashSet;
///
/// let a = HashSet::from_iter(&[1, 2, 3]);
/// let b = HashSet::new();
///
/// assert!(a.pin().is_disjoint(&b.pin()));
/// b.pin().insert(4);
/// assert!(a.pin().is_disjoint(&b.pin()));
/// b.pin().insert(1);
/// assert!(!a.pin().is_disjoint(&b.pin()));
///
/// ```
pub fn is_disjoint(
&self,
other: &HashSet<T, S>,
our_guard: &Guard,
their_guard: &Guard,
) -> bool {
for value in self.iter(our_guard) {
if other.contains(&value, their_guard) {
return false;
}
}

true
}

/// Returns `true` if the set is a subset of another, i.e., `other` contains at least all the values in `self`.
///
/// # Examples
///
/// ```
/// use std::iter::FromIterator;
/// use flurry::HashSet;
///
/// let sup = HashSet::from_iter(&[1, 2, 3]);
/// let set = HashSet::new();
///
/// assert!(set.pin().is_subset(&sup.pin()));
/// set.pin().insert(2);
/// assert!(set.pin().is_subset(&sup.pin()));
/// set.pin().insert(4);
/// assert!(!set.pin().is_subset(&sup.pin()));
/// ```
pub fn is_subset(&self, other: &HashSet<T, S>, our_guard: &Guard, their_guard: &Guard) -> bool {
for value in self.iter(our_guard) {
if !other.contains(&value, their_guard) {
return false;
}
}

true
}

/// Returns `true` if the set is a superset of another, i.e., `self` contains at least all the values in `other`.
///
/// # Examples
///
/// ```
/// use std::iter::FromIterator;
/// use flurry::HashSet;
///
/// let sub = HashSet::from_iter(&[1, 2]);
/// let set = HashSet::new();
///
/// assert!(!set.pin().is_superset(&sub.pin()));
///
/// set.pin().insert(0);
/// set.pin().insert(1);
/// assert!(!set.pin().is_superset(&sub.pin()));
///
/// set.pin().insert(2);
/// assert!(set.pin().is_superset(&sub.pin()));
/// ```
pub fn is_superset(
&self,
other: &HashSet<T, S>,
our_guard: &Guard,
their_guard: &Guard,
) -> bool {
other.is_subset(self, their_guard, our_guard)
}

pub(crate) fn guarded_eq(&self, other: &Self, our_guard: &Guard, their_guard: &Guard) -> bool {
self.map.guarded_eq(&other.map, our_guard, their_guard)
}
}

impl<T, S> HashSet<T, S>
Expand All @@ -301,7 +396,7 @@ where
/// assert_eq!(set.insert(2, &guard), false);
/// assert!(set.contains(&2, &guard));
/// ```
pub fn insert<'g>(&'g self, value: T, guard: &'g Guard) -> bool {
pub fn insert(&self, value: T, guard: &Guard) -> bool {
let old = self.map.insert(value, (), guard);
old.is_none()
}
Expand Down Expand Up @@ -332,7 +427,7 @@ where
/// assert!(!set.contains(&2, &guard));
/// assert_eq!(set.remove(&2, &guard), false);
/// ```
pub fn remove<'g, Q>(&'g self, value: &Q, guard: &'g Guard) -> bool
pub fn remove<Q>(&self, value: &Q, guard: &Guard) -> bool
where
T: Borrow<Q>,
Q: ?Sized + Hash + Eq,
Expand Down Expand Up @@ -367,6 +462,60 @@ where
{
self.map.remove_entry(value, guard).map(|(k, _)| k)
}

/// Retains only the elements specified by the predicate.
///
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
///
/// # Examples
///
/// ```
/// use flurry::HashSet;
///
/// let set = HashSet::new();
///
/// for i in 0..8 {
/// set.pin().insert(i);
/// }
/// set.pin().retain(|&e| e % 2 == 0);
/// assert_eq!(set.pin().len(), 4);
/// ```
pub fn retain<F>(&self, mut f: F, guard: &Guard)
where
F: FnMut(&T) -> bool,
{
self.map.retain(|value, ()| f(value), guard)
}
}

impl<T, S> HashSet<T, S>
where
T: Clone,
{
/// Clears the set, removing all elements.
///
/// # Examples
///
/// ```
/// use flurry::HashSet;
///
/// let set = HashSet::new();
///
/// set.pin().insert("a");
/// set.pin().clear();
/// assert!(set.pin().is_empty());
/// ```
pub fn clear(&self, guard: &Guard) {
self.map.clear(guard)
}

/// Tries to reserve capacity for at least `additional` more elements to
/// be inserted in the `HashSet`.
///
/// The collection may reserve more space to avoid frequent reallocations.
pub fn reserve(&self, additional: usize, guard: &Guard) {
self.map.reserve(additional, guard)
}
}

impl<T, S> PartialEq for HashSet<T, S>
Expand Down
Loading

0 comments on commit d1f67c2

Please sign in to comment.