1use super::{
2 cache_cell::CacheCell,
3 dep_node::{DepNode, Dependent},
4 Storage,
5};
6use hashbrown::{
7 hash_map::{DefaultHashBuilder, RawEntryMut},
8 HashMap,
9};
10
11use std::{
12 any::type_name,
13 borrow::Borrow,
14 fmt::{Debug, Formatter, Result as FmtResult},
15 hash::{BuildHasher, Hash, Hasher},
16 marker::PhantomData,
17};
18
19#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
22pub struct KeyMiss<'k, K: ?Sized, I, H> {
23 inner: Result<Hashed<&'k K, H>, &'k K>,
24 dependent: Dependent,
25 node: Option<DepNode>,
26 input: I,
27}
28
29impl<'k, K: ?Sized, I, H> KeyMiss<'k, K, I, H> {
30 fn hashed(h: Hashed<&'k K, H>, input: I, node: Option<DepNode>, dependent: Dependent) -> Self {
31 Self { inner: Ok(h), node, dependent, input }
32 }
33
34 pub(crate) fn just_key(k: &'k K, input: I, dependent: Dependent, revision: u64) -> Self {
35 let node = DepNode::new(dependent, revision);
36 let dependent = node.as_dependent();
37 Self { inner: Err(k), dependent, node: Some(node), input }
38 }
39
40 pub(crate) fn init<R>(&self, op: impl FnOnce(&I) -> R) -> R {
41 self.dependent.clone().init_dependency(|| op(&self.input))
42 }
43}
44
45impl<'k, K, I, H> Debug for KeyMiss<'k, K, I, H>
46where
47 K: Debug + ?Sized,
48 I: Debug,
49{
50 fn fmt(&self, f: &mut Formatter) -> FmtResult {
51 f.debug_struct("KeyMiss")
52 .field("inner", &self.inner)
53 .field("dependent", &self.dependent)
54 .field("node", &self.node)
55 .field("input", &self.input)
56 .finish()
57 }
58}
59
60#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
63struct Hashed<K, H> {
64 key: K,
65 hash: u64,
66 hasher: PhantomData<H>,
67}
68
69impl<K, H> Debug for Hashed<K, H>
70where
71 K: Debug,
72{
73 fn fmt(&self, f: &mut Formatter) -> FmtResult {
74 f.debug_struct("Hashed")
75 .field("key", &self.key)
76 .field("hash", &self.hash)
77 .field("hasher", &std::any::type_name::<H>())
78 .finish()
79 }
80}
81
82#[derive(Clone)]
84pub(crate) struct Namespace<Scope, Input, Output, H = DefaultHashBuilder> {
85 inner: HashMap<Scope, CacheCell<Input, Output>, H>,
86}
87
88impl<Scope, Input, Output, H> Default for Namespace<Scope, Input, Output, H>
89where
90 H: Default,
91{
92 fn default() -> Self {
93 Self { inner: Default::default() }
94 }
95}
96
97impl<Scope, Input, Output, H> Namespace<Scope, Input, Output, H>
98where
99 Scope: Eq + Hash + 'static,
100 Input: 'static,
101 Output: 'static,
102 H: BuildHasher,
103{
104 fn hashed<'k, Key>(&self, key: &'k Key) -> Hashed<&'k Key, H>
105 where
106 Key: Hash + ?Sized,
107 {
108 let mut hasher = self.inner.hasher().build_hasher();
109 key.hash(&mut hasher);
110 Hashed { key, hash: hasher.finish(), hasher: PhantomData }
111 }
112
113 fn entry<'k, Key>(
114 &self,
115 hashed: &Hashed<&'k Key, H>,
116 ) -> Option<(&Scope, &CacheCell<Input, Output>)>
117 where
118 Key: Eq + ?Sized,
119 Scope: Borrow<Key>,
120 {
121 self.inner.raw_entry().from_hash(hashed.hash, |q| q.borrow().eq(hashed.key))
122 }
123
124 fn entry_mut<'k, Key>(
125 &mut self,
126 hashed: &Hashed<&'k Key, H>,
127 ) -> RawEntryMut<Scope, CacheCell<Input, Output>, H>
128 where
129 Key: Eq + ?Sized,
130 Scope: Borrow<Key>,
131 {
132 self.inner.raw_entry_mut().from_hash(hashed.hash, |q| q.borrow().eq(hashed.key))
133 }
134
135 pub fn get<'k, Key, Arg>(
136 &self,
137 key: &'k Key,
138 arg: &Arg,
139 dependent: Dependent,
140 revision: u64,
141 ) -> Result<&Output, KeyMiss<'k, Key, Input, H>>
142 where
143 Key: Eq + Hash + ?Sized,
144 Scope: Borrow<Key>,
145 Arg: PartialEq<Input> + ToOwned<Owned = Input> + ?Sized,
146 Input: Borrow<Arg>,
147 {
148 let hashed = self.hashed(key);
149 if let Some((_, cell)) = self.entry(&hashed) {
150 cell.get(arg, dependent).map_err(|d| KeyMiss::hashed(hashed, arg.to_owned(), None, d))
151 } else {
152 let node = DepNode::new(dependent, revision);
153 let new_dep = node.as_dependent();
154 Err(KeyMiss::hashed(hashed, arg.to_owned(), Some(node), new_dep))
155 }
156 }
157
158 pub fn store<Key>(&mut self, miss: KeyMiss<'_, Key, Input, H>, output: Output, revision: u64)
159 where
160 Key: Eq + Hash + ToOwned<Owned = Scope> + ?Sized,
161 Scope: Borrow<Key>,
162 {
163 let dependent = miss.dependent;
164 let hashed = miss.inner.unwrap_or_else(|k| self.hashed(k));
165 match self.entry_mut(&hashed) {
166 RawEntryMut::Occupied(occ) => {
167 assert!(miss.node.is_none(), "mustn't create nodes that aren't used");
168 occ.into_mut().store(miss.input, output, dependent, revision);
169 }
170 RawEntryMut::Vacant(vac) => {
171 vac.insert(
172 hashed.key.to_owned(),
173 CacheCell::new(
174 miss.input,
175 output,
176 miss.node.expect("if no cell present, we must have created a fresh node"),
177 ),
178 );
179 }
180 }
181 }
182}
183
184impl<Scope, Input, Output, H> Storage for Namespace<Scope, Input, Output, H>
185where
186 Scope: 'static,
187 Input: 'static,
188 Output: 'static,
189 H: 'static,
190{
191 fn mark(&mut self, revision: u64) {
192 self.inner.values_mut().for_each(|c| c.update_liveness(revision));
193 }
194
195 fn sweep(&mut self) {
196 self.inner.retain(|_, c| {
197 let keep = c.is_live();
198 c.mark_dead();
199 keep
200 });
201 }
202}
203
204impl<Scope, Input, Output, H> Debug for Namespace<Scope, Input, Output, H> {
205 fn fmt(&self, f: &mut Formatter) -> FmtResult {
207 f.debug_map()
209 .entry(&"scope", &type_name::<Scope>())
210 .entry(&"input", &type_name::<Input>())
211 .entry(&"output", &type_name::<Output>())
212 .finish()
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use super::*;
219
220 #[test]
221 fn namespace_debug_output() {
222 let ns: Namespace<u8, u8, u8> = Default::default();
223 let output = format!("{:?}", ns);
224 assert_eq!(output, "{\"scope\": \"u8\", \"input\": \"u8\", \"output\": \"u8\"}");
225 }
226}