Skip to main content

cons/
lib.rs

1/*!
2# cons
3[![crates.io](https://img.shields.io/crates/v/pour)](https://crates.io/crates/cons)
4[![Downloads](https://img.shields.io/crates/d/pour)](https://crates.io/crates/cons)
5[![Documentation](https://docs.rs/pour/badge.svg)](https://docs.rs/cons/)
6[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
8Quick and simple hash-consing implementations for a variety of internally mutable `HashMap`s/`HashSet`s (use the features to select the ones you want).
9*/
10use std::rc::Rc;
11use std::sync::Arc;
12
13/// A trait implemented by sets which can be used for hash-consing values of type `C` using keys of type `Q`
14pub trait Cons<C, Q> {
15    /// Cons a key of type `Q` into a cached key of type `C`
16    fn cons(&self, key: Q) -> C;
17}
18
19/// A trait implemented by values which can be garbage collected
20pub trait CanGC {
21    /// Whether this value only has a single reference to it, and therefore can be garbage collected
22    fn single_reference(&self) -> bool;
23    /// Whether this value has two or less references to it, and therefore can be garbage collected by an object holding
24    /// the other reference
25    fn double_reference(&self) -> bool;
26}
27
28/// A trait implemented by sets which can be used to un-cons values of type `C`
29pub trait Uncons<C> {
30    /// Garbage collect a value of type `C`, removing it if there cannot be any other references to it.
31    /// If this is the case, return `true`, otherwise return `false`.
32    #[inline(always)]
33    fn gc(&self, key: &mut C) -> bool
34    where
35        C: CanGC,
36    {
37        if key.double_reference() {
38            self.uncons(key)
39        } else {
40            false
41        }
42    }
43    /// Unconditionally remove a value of type `C`. Return whether it was in the set
44    fn uncons(&self, key: &mut C) -> bool;
45}
46
47impl<C> CanGC for Arc<C> {
48    #[inline]
49    fn single_reference(&self) -> bool {
50        Arc::weak_count(self) + Arc::strong_count(self) <= 1
51    }
52    #[inline(always)]
53    fn double_reference(&self) -> bool {
54        Arc::weak_count(self) + Arc::strong_count(self) <= 2
55    }
56}
57
58impl<C> CanGC for Rc<C> {
59    #[inline]
60    fn single_reference(&self) -> bool {
61        Rc::weak_count(self) + Rc::strong_count(self) <= 1
62    }
63    #[inline(always)]
64    fn double_reference(&self) -> bool {
65        Rc::weak_count(self) + Rc::strong_count(self) <= 2
66    }
67}
68
69#[cfg(feature = "elysees")]
70mod elysees_impl;#[cfg(feature = "flurry-cons")]
71pub mod flurry_cons;