Skip to main content

cljrs_value/collections/
transient_set.rs

1use crate::hash::hash_combine_unordered;
2use crate::{ClojureHash, PersistentHashSet, Value, ValueError, ValueResult};
3use std::sync::Mutex;
4
5#[derive(Debug)]
6pub struct TransientSet {
7    set: Mutex<PersistentHashSet>,
8    persisted: Mutex<bool>,
9}
10
11impl TransientSet {
12    pub fn new() -> Self {
13        TransientSet {
14            set: Mutex::new(PersistentHashSet::empty()),
15            persisted: Mutex::new(false),
16        }
17    }
18
19    pub fn new_from_set(set: &PersistentHashSet) -> TransientSet {
20        TransientSet {
21            set: Mutex::new(set.clone()),
22            persisted: Mutex::new(false),
23        }
24    }
25
26    pub fn conj(&self, value: Value) -> ValueResult<()> {
27        if *self.persisted.lock().unwrap() {
28            return Err(ValueError::TransientAlreadyPersisted);
29        }
30        let mut set = self.set.lock().unwrap();
31        set.conj_mut(value);
32        Ok(())
33    }
34
35    pub fn disj(&self, value: &Value) -> ValueResult<()> {
36        if *self.persisted.lock().unwrap() {
37            return Err(ValueError::TransientAlreadyPersisted);
38        }
39        let mut set = self.set.lock().unwrap();
40        *set = set.disj(value);
41        Ok(())
42    }
43
44    pub fn persistent(&self) -> ValueResult<PersistentHashSet> {
45        let set = self.set.lock().unwrap();
46        let mut persisted = self.persisted.lock().unwrap();
47        if *persisted {
48            return Err(ValueError::TransientAlreadyPersisted);
49        }
50        *persisted = true;
51        Ok(set.clone())
52    }
53
54    pub fn count(&self) -> usize {
55        let set = self.set.lock().unwrap();
56        set.count()
57    }
58
59    pub fn contains(&self, value: &Value) -> bool {
60        self.set.lock().unwrap().contains(value)
61    }
62}
63
64impl Clone for TransientSet {
65    fn clone(&self) -> Self {
66        Self {
67            set: Mutex::new(self.set.lock().unwrap().clone()),
68            persisted: Mutex::new(*self.persisted.lock().unwrap()),
69        }
70    }
71}
72
73impl ClojureHash for TransientSet {
74    fn clojure_hash(&self) -> u32 {
75        let mut hash: u32 = 0;
76        for v in self.set.lock().unwrap().iter() {
77            hash = hash_combine_unordered(hash, v.clojure_hash())
78        }
79        hash
80    }
81}
82
83impl cljrs_gc::Trace for TransientSet {
84    fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
85        {
86            let set = self.set.lock().unwrap();
87            for v in set.iter() {
88                v.trace(visitor);
89            }
90        }
91    }
92
93    fn gc_size_extra(&self) -> usize {
94        let set = self.set.lock().unwrap();
95        set.full_size_extra()
96    }
97}
98
99impl Default for TransientSet {
100    fn default() -> Self {
101        Self::new()
102    }
103}