Skip to content
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

Finish fixing #17 #78

Merged
merged 15 commits into from
Mar 27, 2020
Merged
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
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