1use std::fmt::Debug;
2use crate::dag_uid::RxDAGUid;
3use crate::rx_impl::{RxDAGElem, RxImpl, Rx, RxEdgeImpl};
4use crate::rx_ref::{RxRef, Var, CRx};
5use crate::misc::frozen_vec::{FrozenVec, FrozenSlice};
6use crate::misc::assert_variance::assert_is_covariant;
7use crate::misc::slice_split3::SliceSplit3;
8
9pub trait RxContext<'a, 'c: 'a> {
14 fn sub_dag(self) -> RxSubDAG<'a, 'c>;
15}
16
17pub trait MutRxContext<'a, 'c: 'a> {
22 fn sub_dag(self) -> RxSubDAG<'a, 'c>;
23}
24
25#[derive(Debug)]
61pub struct RxDAG<'c>(FrozenVec<RxDAGElem<'c>>, RxDAGUid<'c>);
62
63#[derive(Debug, Clone, Copy)]
65pub struct RxDAGSnapshot<'a, 'c: 'a>(&'a RxDAG<'c>);
66
67#[doc(hidden)]
69#[derive(Debug, Clone, Copy)]
70pub struct RxSubDAG<'a, 'c: 'a> {
71 pub(crate) before: FrozenSlice<'a, RxDAGElem<'c>>,
72 pub(crate) index: usize,
73 pub(crate) id: RxDAGUid<'c>
74}
75assert_is_covariant!(for['a] (RxSubDAG<'a, 'c>) over 'c);
76
77#[derive(Debug, Clone, Copy)]
79pub struct RxInput<'a, 'c: 'a>(pub(crate) RxSubDAG<'a, 'c>);
80
81impl<'c> RxDAG<'c> {
82 pub fn new() -> Self {
84 Self(FrozenVec::new(), RxDAGUid::next())
85 }
86
87 pub fn new_var<T: 'c>(&self, init: T) -> Var<'c, T> {
89 let index = self.next_index();
90 let rx = RxImpl::new(init);
91 self.0.push(RxDAGElem::Node(Box::new(rx)));
92 Var::new(RxRef::new(self, index))
93 }
94
95 pub fn run_crx<F: FnMut(RxInput<'_, 'c>) + 'c>(&self, mut compute: F) {
99 let mut input_backwards_offsets = Vec::new();
100 let () = Self::run_compute(&mut compute, RxInput(self.sub_dag()), &mut input_backwards_offsets);
101 let compute_edge = RxEdgeImpl::<'c, _>::new(input_backwards_offsets, 0, move |mut input_backwards_offsets: &mut Vec<usize>, input: RxInput<'_, 'c>, outputs: &mut dyn Iterator<Item=&Rx<'c>>| {
102 input_backwards_offsets.clear();
103 let () = Self::run_compute(&mut compute, input, &mut input_backwards_offsets);
104 debug_assert!(outputs.next().is_none());
105 });
106 self.0.push(RxDAGElem::Edge(Box::new(compute_edge)));
107 }
108
109 pub fn new_crx<T: 'c, F: FnMut(RxInput<'_, 'c>) -> T + 'c>(&self, mut compute: F) -> CRx<'c, T> {
111 let mut input_backwards_offsets = Vec::new();
112 let init = Self::run_compute(&mut compute, RxInput(self.sub_dag()), &mut input_backwards_offsets);
113 let compute_edge = RxEdgeImpl::<'c, _>::new(input_backwards_offsets, 1, move |mut input_backwards_offsets: &mut Vec<usize>, input: RxInput<'_, 'c>, outputs: &mut dyn Iterator<Item=&Rx<'c>>| {
114 input_backwards_offsets.clear();
115 let output = Self::run_compute(&mut compute, input, &mut input_backwards_offsets);
116 unsafe { outputs.next().unwrap().set_dyn(output); }
117 debug_assert!(outputs.next().is_none());
118 });
119 self.0.push(RxDAGElem::Edge(Box::new(compute_edge)));
120
121 let index = self.next_index();
122 let rx = RxImpl::new(init);
123 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx)));
124 CRx::new(RxRef::new(self, index))
125 }
126
127 pub fn new_crx2<T1: 'c, T2: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2) + 'c>(&self, mut compute: F) -> (CRx<'c, T1>, CRx<'c, T2>) {
129 let mut input_backwards_offsets = Vec::new();
130 let (init1, init2) = Self::run_compute(&mut compute, RxInput(self.sub_dag()), &mut input_backwards_offsets);
131 let compute_edge = RxEdgeImpl::<'c, _>::new(input_backwards_offsets, 2, move |mut input_backwards_offsets: &mut Vec<usize>, input: RxInput<'_, 'c>, outputs: &mut dyn Iterator<Item=&Rx<'c>>| {
132 input_backwards_offsets.clear();
133 let (output1, output2) = Self::run_compute(&mut compute, input, &mut input_backwards_offsets);
134 unsafe { outputs.next().unwrap().set_dyn(output1); }
135 unsafe { outputs.next().unwrap().set_dyn(output2); }
136 debug_assert!(outputs.next().is_none());
137 });
138 self.0.push(RxDAGElem::Edge(Box::new(compute_edge)));
139
140 let index = self.next_index();
141 let rx1 = RxImpl::new(init1);
142 let rx2 = RxImpl::new(init2);
143 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx1)));
144 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx2)));
145 (CRx::new(RxRef::new(self, index)), CRx::new(RxRef::new(self, index + 1)))
146 }
147
148 pub fn new_crx3<T1: 'c, T2: 'c, T3: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3) + 'c>(&self, mut compute: F) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>) {
150 let mut input_backwards_offsets = Vec::new();
151 let (init1, init2, init3) = Self::run_compute(&mut compute, RxInput(self.sub_dag()), &mut input_backwards_offsets);
152 let compute_edge = RxEdgeImpl::<'c, _>::new(input_backwards_offsets, 3, move |mut input_backwards_offsets: &mut Vec<usize>, input: RxInput<'_, 'c>, outputs: &mut dyn Iterator<Item=&Rx<'c>>| {
153 input_backwards_offsets.clear();
154 let (output1, output2, output3) = Self::run_compute(&mut compute, input, &mut input_backwards_offsets);
155 unsafe { outputs.next().unwrap().set_dyn(output1); }
156 unsafe { outputs.next().unwrap().set_dyn(output2); }
157 unsafe { outputs.next().unwrap().set_dyn(output3); }
158 debug_assert!(outputs.next().is_none());
159 });
160 self.0.push(RxDAGElem::Edge(Box::new(compute_edge)));
161
162 let index = self.next_index();
163 let rx1 = RxImpl::new(init1);
164 let rx2 = RxImpl::new(init2);
165 let rx3 = RxImpl::new(init3);
166 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx1)));
167 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx2)));
168 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx3)));
169 (CRx::new(RxRef::new(self, index)), CRx::new(RxRef::new(self, index + 1)), CRx::new(RxRef::new(self, index + 2)))
170 }
171
172 pub fn new_crx4<T1: 'c, T2: 'c, T3: 'c, T4: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3, T4) + 'c>(&self, mut compute: F) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>, CRx<'c, T4>) {
174 let mut input_backwards_offsets = Vec::new();
175 let (init1, init2, init3, init4) = Self::run_compute(&mut compute, RxInput(self.sub_dag()), &mut input_backwards_offsets);
176 let compute_edge = RxEdgeImpl::<'c, _>::new(input_backwards_offsets, 4, move |mut input_backwards_offsets: &mut Vec<usize>, input: RxInput<'_, 'c>, outputs: &mut dyn Iterator<Item=&Rx<'c>>| {
177 input_backwards_offsets.clear();
178 let (output1, output2, output3, output4) = Self::run_compute(&mut compute, input, &mut input_backwards_offsets);
179 unsafe { outputs.next().unwrap().set_dyn(output1); }
180 unsafe { outputs.next().unwrap().set_dyn(output2); }
181 unsafe { outputs.next().unwrap().set_dyn(output3); }
182 unsafe { outputs.next().unwrap().set_dyn(output4); }
183 debug_assert!(outputs.next().is_none());
184 });
185 self.0.push(RxDAGElem::Edge(Box::new(compute_edge)));
186
187 let index = self.next_index();
188 let rx1 = RxImpl::new(init1);
189 let rx2 = RxImpl::new(init2);
190 let rx3 = RxImpl::new(init3);
191 let rx4 = RxImpl::new(init4);
192 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx1)));
193 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx2)));
194 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx3)));
195 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx4)));
196 (CRx::new(RxRef::new(self, index)), CRx::new(RxRef::new(self, index + 1)), CRx::new(RxRef::new(self, index + 2)), CRx::new(RxRef::new(self, index + 3)))
197 }
198
199 pub fn new_crx5<T1: 'c, T2: 'c, T3: 'c, T4: 'c, T5: 'c, F: FnMut(RxInput<'_, 'c>) -> (T1, T2, T3, T4, T5) + 'c>(&self, mut compute: F) -> (CRx<'c, T1>, CRx<'c, T2>, CRx<'c, T3>, CRx<'c, T4>, CRx<'c, T5>) {
201 let mut input_backwards_offsets = Vec::new();
202 let (init1, init2, init3, init4, init5) = Self::run_compute(&mut compute, RxInput(self.sub_dag()), &mut input_backwards_offsets);
203 let compute_edge = RxEdgeImpl::<'c, _>::new(input_backwards_offsets, 5, move |mut input_backwards_offsets: &mut Vec<usize>, input: RxInput<'_, 'c>, outputs: &mut dyn Iterator<Item=&Rx<'c>>| {
204 input_backwards_offsets.clear();
205 let (output1, output2, output3, output4, output5) = Self::run_compute(&mut compute, input, &mut input_backwards_offsets);
206 unsafe { outputs.next().unwrap().set_dyn(output1); }
207 unsafe { outputs.next().unwrap().set_dyn(output2); }
208 unsafe { outputs.next().unwrap().set_dyn(output3); }
209 unsafe { outputs.next().unwrap().set_dyn(output4); }
210 unsafe { outputs.next().unwrap().set_dyn(output5); }
211 debug_assert!(outputs.next().is_none());
212 });
213 self.0.push(RxDAGElem::Edge(Box::new(compute_edge)));
214
215 let index = self.next_index();
216 let rx1 = RxImpl::new(init1);
217 let rx2 = RxImpl::new(init2);
218 let rx3 = RxImpl::new(init3);
219 let rx4 = RxImpl::new(init4);
220 let rx5 = RxImpl::new(init5);
221 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx1)));
222 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx2)));
223 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx3)));
224 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx4)));
225 self.0.push(RxDAGElem::<'c>::Node(Box::new(rx5)));
226 (CRx::new(RxRef::new(self, index)), CRx::new(RxRef::new(self, index + 1)), CRx::new(RxRef::new(self, index + 2)), CRx::new(RxRef::new(self, index + 3)), CRx::new(RxRef::new(self, index + 4)))
227 }
228
229 fn next_index(&self) -> usize {
232 self.0.len()
233 }
234
235 fn run_compute<T, F: FnMut(RxInput<'_, 'c>) -> T + 'c>(compute: &mut F, input: RxInput<'_, 'c>, input_backwards_offsets: &mut Vec<usize>) -> T {
236 debug_assert!(input_backwards_offsets.is_empty());
237
238 let result = compute(input);
239 let input_indices = input.post_read();
240
241 input_indices
242 .into_iter()
243 .map(|index| input.0.index - index)
244 .collect_into(input_backwards_offsets);
245 result
246 }
247
248 pub fn recompute(&mut self) {
252 for (index, (before, current, after)) in self.0.as_mut().iter_mut_split3s().enumerate() {
253 current.recompute(index, before, after, self.1);
254 }
255
256 for current in self.0.as_mut().iter_mut() {
257 current.post_recompute();
258 }
259 }
260
261 pub fn now(&mut self) -> RxDAGSnapshot<'_, 'c> {
263 self.recompute();
264 RxDAGSnapshot(self)
265 }
266
267 pub fn stale(&self) -> RxDAGSnapshot<'_, 'c> {
270 RxDAGSnapshot(self)
271 }
272
273 pub(crate) fn id(&self) -> RxDAGUid<'c> {
274 self.1
275 }
276}
277
278impl<'a, 'c: 'a> RxContext<'a, 'c> for RxDAGSnapshot<'a, 'c> {
279 fn sub_dag(self) -> RxSubDAG<'a, 'c> {
280 RxSubDAG {
281 before: FrozenSlice::from(&self.0.0),
282 index: self.0.0.len(),
283 id: self.0.1
284 }
285 }
286}
287
288impl<'a, 'c: 'a> MutRxContext<'a, 'c> for &'a RxDAG<'c> {
289 fn sub_dag(self) -> RxSubDAG<'a, 'c> {
290 RxDAGSnapshot(self).sub_dag()
291 }
292}
293
294impl<'a, 'c: 'a> RxContext<'a, 'c> for RxInput<'a, 'c> {
295 fn sub_dag(self) -> RxSubDAG<'a, 'c> {
296 self.0
297 }
298}
299
300impl<'a, 'c: 'a> RxInput<'a, 'c> {
301 fn post_read(&self) -> Vec<usize> {
302 let mut results = Vec::new();
303 for (index, current) in self.0.before.iter().enumerate() {
304 if current.post_read() {
305 results.push(index)
306 }
307 }
308 results
309 }
310}