flurry 0.5.2

Rust port of Java's ConcurrentHashMap
Documentation
use crate::iter::*;
use crate::reclaim::{Guard, GuardRef};
use crate::HashSet;
use std::borrow::Borrow;
use std::fmt::{self, Debug, Formatter};
use std::hash::{BuildHasher, Hash};

/// A reference to a [`HashSet`], constructed with [`HashSet::pin`] or [`HashSet::with_guard`].
///
/// The current thread will be pinned for the duration of this reference.
/// Keep in mind that this prevents the collection of garbage generated by the set.
pub struct HashSetRef<'set, T, S = crate::DefaultHashBuilder> {
    pub(crate) set: &'set HashSet<T, S>,
    guard: GuardRef<'set>,
}

impl<T, S> HashSet<T, S> {
    /// Get a reference to this set with the current thread pinned.
    ///
    /// Keep in mind that for as long as you hold onto this, you are preventing the collection of
    /// garbage generated by the set.
    pub fn pin(&self) -> HashSetRef<'_, T, S> {
        HashSetRef {
            guard: GuardRef::Owned(self.guard()),
            set: self,
        }
    }

    /// Get a reference to this set with the given guard.
    pub fn with_guard<'g>(&'g self, guard: &'g Guard<'_>) -> HashSetRef<'g, T, S> {
        HashSetRef {
            guard: GuardRef::Ref(guard),
            set: self,
        }
    }
}

impl<T, S> HashSetRef<'_, T, S> {
    /// Returns the number of elements in the set.
    ///
    /// See also [`HashSet::len`].
    pub fn len(&self) -> usize {
        self.set.len()
    }

    /// Returns `true` if the set is empty. Otherwise returns `false`.
    ///
    /// See also [`HashSet::is_empty`].
    pub fn is_empty(&self) -> bool {
        self.set.is_empty()
    }

    /// An iterator visiting all elements in arbitrary order.
    ///
    /// The iterator element type is `&'g T`.
    ///
    /// See also [`HashSet::iter`].
    pub fn iter(&self) -> Keys<'_, T, ()> {
        self.set.iter(&self.guard)
    }
}

impl<T, S> HashSetRef<'_, T, S>
where
    T: Hash + Ord,
    S: BuildHasher,
{
    /// Returns `true` if the given value is an element of this set.
    ///
    /// See also [`HashSet::contains`].
    #[inline]
    pub fn contains<Q>(&self, value: &Q) -> bool
    where
        T: Borrow<Q>,
        Q: ?Sized + Hash + Ord,
    {
        self.set.contains(value, &self.guard)
    }

    /// Returns a reference to the element in the set, if any, that is equal to the given value.
    ///
    /// See also [`HashSet::get`].
    pub fn get<'g, Q>(&'g self, value: &Q) -> Option<&'g T>
    where
        T: Borrow<Q>,
        Q: ?Sized + Hash + Ord,
    {
        self.set.get(value, &self.guard)
    }

    /// Returns `true` if `self` has no elements in common with `other`.
    ///
    /// See also [`HashSet::is_disjoint`].
    pub fn is_disjoint(&self, other: &HashSetRef<'_, T, S>) -> bool {
        self.set.is_disjoint(other.set, &self.guard, &other.guard)
    }

    /// Returns `true` if the set is a subset of another, i.e., `other` contains at least all the values in `self`.
    ///
    /// See also [`HashSet::is_subset`].
    pub fn is_subset(&self, other: &HashSetRef<'_, T, S>) -> bool {
        self.set.is_subset(other.set, &self.guard, &other.guard)
    }

    /// Returns `true` if the set is a superset of another, i.e., `self` contains at least all the values in `other`.
    ///
    /// See also [`HashSet::is_superset`].
    pub fn is_superset(&self, other: &HashSetRef<'_, T, S>) -> bool {
        self.set.is_superset(other.set, &self.guard, &other.guard)
    }
}

impl<T, S> HashSetRef<'_, T, S>
where
    T: Sync + Send + Clone + Hash + Ord,
    S: BuildHasher,
{
    /// Adds a value to the set.
    ///
    /// See also [`HashSet::insert`].
    pub fn insert(&self, value: T) -> bool {
        self.set.insert(value, &self.guard)
    }

    /// Removes a value from the set.
    ///
    /// See also [`HashSet::remove`].
    pub fn remove<Q>(&self, value: &Q) -> bool
    where
        T: Borrow<Q>,
        Q: ?Sized + Hash + Ord,
    {
        self.set.remove(value, &self.guard)
    }

    /// Removes and returns the value in the set, if any, that is equal to the given one.
    ///
    /// See also [`HashSet::take`].
    pub fn take<'g, Q>(&'g self, value: &Q) -> Option<&'g T>
    where
        T: Borrow<Q>,
        Q: ?Sized + Hash + Ord,
    {
        self.set.take(value, &self.guard)
    }

    /// Retains only the elements specified by the predicate.
    ///
    /// See also [`HashSet::retain`].
    pub fn retain<F>(&self, f: F)
    where
        F: FnMut(&T) -> bool,
    {
        self.set.retain(f, &self.guard);
    }
}

impl<T, S> HashSetRef<'_, T, S>
where
    T: Clone + Ord,
{
    /// Clears the set, removing all elements.
    ///
    /// See also [`HashSet::clear`].
    pub fn clear(&self) {
        self.set.clear(&self.guard);
    }

    /// Tries to reserve capacity for at least `additional` more elements to
    /// be inserted into the underlying `HashSet`.
    ///
    /// See also [`HashSet::reserve`].
    pub fn reserve(&self, additional: usize) {
        self.set.reserve(additional, &self.guard)
    }
}

impl<'g, T, S> IntoIterator for &'g HashSetRef<'_, T, S> {
    type IntoIter = Keys<'g, T, ()>;
    type Item = &'g T;

    fn into_iter(self) -> Self::IntoIter {
        self.set.iter(&self.guard)
    }
}

impl<T, S> Debug for HashSetRef<'_, T, S>
where
    T: Debug,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_set().entries(self).finish()
    }
}

impl<T, S> Clone for HashSetRef<'_, T, S> {
    fn clone(&self) -> Self {
        self.set.pin()
    }
}

impl<T, S> PartialEq for HashSetRef<'_, T, S>
where
    T: Hash + Ord,
    S: BuildHasher,
{
    fn eq(&self, other: &Self) -> bool {
        self.set == other.set
    }
}

impl<T, S> PartialEq<HashSet<T, S>> for HashSetRef<'_, T, S>
where
    T: Hash + Ord,
    S: BuildHasher,
{
    fn eq(&self, other: &HashSet<T, S>) -> bool {
        self.set.guarded_eq(other, &self.guard, &other.guard())
    }
}

impl<T, S> PartialEq<HashSetRef<'_, T, S>> for HashSet<T, S>
where
    T: Hash + Ord,
    S: BuildHasher,
{
    fn eq(&self, other: &HashSetRef<'_, T, S>) -> bool {
        self.guarded_eq(other.set, &self.guard(), &other.guard)
    }
}

impl<T, S> Eq for HashSetRef<'_, T, S>
where
    T: Hash + Ord,
    S: BuildHasher,
{
}