1#![doc = include_str!("../README.MD")]
2#![warn(missing_docs)]
3#![deny(warnings)]
4#![allow(private_bounds)]
5
6use std::{
7 collections::HashMap,
8 fmt::{Debug, Formatter},
9 marker::PhantomData,
10 ops::Deref,
11 sync::{atomic::AtomicBool, Arc, RwLock, RwLockReadGuard},
12};
13
14use ccutils::{
15 key::Key,
16 sync::{arc_mutex_new, arc_rw_lock_new, ArcMutex, ArcRwLock},
17};
18use linked_hash_map::LinkedHashMap;
19
20trait ComputationValueType {
29 type Type: 'static + Send + Sync;
31}
32
33trait ComputationInputInterface: ComputationValueType {
35 type InputReaderType: InputReader<Self::Type>;
36 fn id(&self) -> ccutils::key::Key;
37 fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>);
39}
40
41trait InputReader<T>: Sync + Send + 'static {
51 type InputGuard<'a>; fn read_input<'a>(&'a self) -> Self::InputGuard<'a>;
53}
54
55impl<T> InputReader<T> for RwLock<T>
56where
57 T: Sync + Send + 'static,
58{
59 type InputGuard<'a> = RwLockReadGuard<'a, T>;
60 fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
61 self.read().unwrap()
62 }
63}
64
65impl<C, T> InputReader<T> for Arc<C>
66where
67 C: InputReader<T>,
68{
69 type InputGuard<'a> = C::InputGuard<'a>;
70 fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
71 self.deref().read_input()
72 }
73}
74
75trait VecInputGuard<C, Marker>
83where
84 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
85{
86 fn as_input_value<'a>(&'a self) -> VecFnArg<'a, C, Marker>;
87}
88
89trait VecInputReader<C, Marker>: Send + Sync + 'static
90where
91 C: Send + Sync + 'static,
92 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
93{
94 fn read_vec_input(&self) -> Box<dyn VecInputGuard<C, Marker> + '_>;
95}
96
97struct VecComputationFArgsSelectorTraitBridge<'b, C> {
98 bridge: Box<dyn Deref<Target = C> + 'b>,
99}
100
101impl<'b, C> VecInputGuard<C, DefaultVariableMarker>
102 for VecComputationFArgsSelectorTraitBridge<'b, C>
103where
104 for<'c> VecComputationFArgsSelector<C, DefaultVariableMarker>:
105 VecComputationFArgsSelectorTrait<FArgs<'c> = &'c C>,
106{
107 fn as_input_value<'a>(&'a self) -> VecFnArg<'a, C, DefaultVariableMarker> {
108 let r: &C = self.bridge.deref();
109 r
110 }
111}
112
113impl<C, T> VecInputReader<C, DefaultVariableMarker> for T
114where
115 T: InputReader<C>,
116 C: Send + Sync + 'static,
117 for<'a> VecComputationFArgsSelector<C, DefaultVariableMarker>:
118 VecComputationFArgsSelectorTrait<FArgs<'a> = &'a C>,
119 for<'a> <T as InputReader<C>>::InputGuard<'a>: Deref<Target = C>,
120{
121 fn read_vec_input(&self) -> Box<dyn VecInputGuard<C, DefaultVariableMarker> + '_> {
122 Box::new(VecComputationFArgsSelectorTraitBridge::<C> {
123 bridge: Box::new(self.read_input()),
124 })
125 }
126}
127
128struct Dependency {
136 key: Key,
137 dependencies: RwLock<HashMap<Key, Arc<Dependency>>>,
138 dependents: RwLock<HashMap<Key, Arc<Dependency>>>,
139 outdated: AtomicBool,
140}
141
142impl Debug for Dependency {
143 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
144 f.debug_struct("")
145 .field("key", &self.key)
146 .field("dependencies", &self.dependencies)
147 .field("dependends count", &self.dependents.read().unwrap().len())
148 .finish()
149 }
150}
151
152impl Dependency {
153 fn new() -> Arc<Self> {
154 Arc::new(Self {
155 key: Key::new(),
156 dependencies: Default::default(),
157 dependents: Default::default(),
158 outdated: AtomicBool::new(false),
159 })
160 }
161 fn from_key(key: Key) -> Arc<Self> {
162 Arc::new(Self {
163 key,
164 dependencies: Default::default(),
165 dependents: Default::default(),
166 outdated: AtomicBool::new(false),
167 })
168 }
169 fn notify_all(&self) {
170 self.outdated
171 .store(true, std::sync::atomic::Ordering::Relaxed);
172 for (_, dep) in self.dependencies.read().unwrap().iter() {
173 dep.notify_all();
174 }
175 }
176 fn insert_dependency(&self, d: Arc<Dependency>) {
177 self.dependencies.write().unwrap().insert(d.key.clone(), d);
178 }
179 fn insert_dependent(&self, d: Arc<Dependency>) {
180 self.dependents.write().unwrap().insert(d.key.clone(), d);
181 }
182 fn remove_dependency(&self, key: &Key) {
183 if let Some(dep) = self.dependencies.write().unwrap().remove(key) {
184 dep.dependents.write().unwrap().remove(&self.key);
185 }
186 }
187 fn link(dependency: &Arc<Dependency>, dependent: Arc<Dependency>) {
188 dependent.insert_dependency(dependency.clone());
189 dependency.insert_dependent(dependent);
190 }
191}
192
193trait ComputationBuilder<T> {
202 type FunctorArgument<'a>;
204 fn prepare<'b>(
206 &self,
207 dependency: &Arc<Dependency>,
208 formula: impl for<'a> Fn(Self::FunctorArgument<'a>) -> T + 'b + Send + Sync,
209 ) -> impl Fn() -> T + 'b + Send + Sync;
210}
211
212trait ComputationVecBuilder<T, Marker> {
213 fn prepare(
214 &self,
215 dependency: &Arc<Dependency>,
216 ) -> LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>>;
217}
218
219macro_rules! computation_builder {
220 ($($type_idx: tt),*) => {
221 paste::paste!{
222 impl<'b, T, $( [<VT $type_idx>], )*> ComputationBuilder<T>
223 for ($(&'b [<VT $type_idx>], )*)
224 where
225 $(
226 [<VT $type_idx>]: ComputationInputInterface,
227 for<'a> <<[<VT $type_idx>] as ComputationInputInterface>::InputReaderType as InputReader
228 <<[<VT $type_idx>] as ComputationValueType>::Type>>::InputGuard<'a>: Deref<Target = <[<VT $type_idx>] as ComputationValueType>::Type>,
229 )*
230 {
231 type FunctorArgument<'a> = ( $(&'a [<VT $type_idx>]::Type, )*);
232 fn prepare<'c>(
233 &self,
234 dependency: &Arc<Dependency>,
235 formula: impl for<'a> Fn(Self::FunctorArgument<'a>) -> T + 'c + Send + Sync,
236 ) -> impl Fn() -> T + 'c + Send + Sync {
237 $(
238 let ([<v $type_idx>], [<dep $type_idx>]) = self.$type_idx.prepare_value();
239 Dependency::link(&dependency, [<dep $type_idx>]);
240 )*
241
242 move || {
243 $(
244 let [<v $type_idx>] = [<v $type_idx>].read_input();
245 )*
246 formula(($( [<v $type_idx>].deref(), )*))
247 }
248 }
249 }
250 impl<'b, T, Marker, $( [<VT $type_idx>], )*> ComputationVecBuilder<T, Marker>
251 for ($(&'b [<VT $type_idx>], )*)
252 where
253 $(
254 [<VT $type_idx>]: ComputationInputInterface<Type = T>,
255 <[<VT $type_idx>] as ComputationInputInterface>::InputReaderType: VecInputReader<T, Marker>,
256 )*
257 T: Sync + Send + 'static,
258 VecComputationFArgsSelector<T, Marker>: VecComputationFArgsSelectorTrait,
259 {
260
261 fn prepare(&self,
262 dependency: &Arc<Dependency>) -> LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>>
263
264 {
265 let mut variables: LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>> = Default::default();
266
267 $(
268 let ([<v $type_idx>], [<dep $type_idx>]) = self.$type_idx.prepare_value();
269 let id = [<dep $type_idx>].key.clone();
270 Dependency::link(&dependency, [<dep $type_idx>]);
271 let [<v $type_idx>]: Box<dyn VecInputReader<T, Marker>> = Box::new([<v $type_idx>]);
272 variables.insert(id, [<v $type_idx>]);
273 )*
274 variables
275 }
276 }
277
278 impl<$( [<VT $type_idx>], )*> ComputationValueType for ($( &[<VT $type_idx>], )*)
281 where
282 $(
283 [<VT $type_idx>]: ComputationInputInterface,
284 )*
285 {
286 type Type = ($([<VT $type_idx>]::Type,)*);
287 }
288 impl<$( [<T $type_idx>], )* $([<IRT $type_idx>], )*> InputReader<($([<T $type_idx>], )*)> for ($([<IRT $type_idx>], )*)
289 where
290 $(
291 [<IRT $type_idx>]: InputReader<[<T $type_idx>]>,
292 )*
293 {
294 type InputGuard<'a> = ($([<IRT $type_idx>]::InputGuard<'a>,)*);
295 fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
296 (
297 $(
298 self.$type_idx.read_input(),
299 )*
300 )
301 }
302 }
303
304 impl<$( [<T $type_idx>], )* $( [<VT $type_idx>], )*> ComputationInputInterface for ($( &[<VT $type_idx>], )*)
305 where
306 $(
307 [<VT $type_idx>]: ComputationInputInterface<Type = [<T $type_idx>]>,
308 [<T $type_idx>]: Send + Sync + 'static,
309 )*
310 {
311 type InputReaderType = ($([<VT $type_idx>]::InputReaderType,)*);
312 fn id(&self) -> Key {
313 let mut v = Vec::<Key>::new();
314 $(
315 v.push(self.$type_idx.id());
316 )*
317 Key::combination(v)
318 }
319 fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
320 let dependency = Dependency::from_key(self.id());
321 $(
322 let ([<input_reader $type_idx>], [<dep $type_idx>]) = self.$type_idx.prepare_value();
323 Dependency::link(&dependency, [<dep $type_idx>]);
324 )*
325 (($([<input_reader $type_idx>], )*), dependency)
326 }
327 }
328
329 impl<$( [<T $type_idx>], )*> VecComputationFArgsSelectorTrait
330 for VecComputationFArgsSelector<($( [<T $type_idx>], )*), markers::GroupedVariables>
331 where
332 $(
333 [<T $type_idx>]: 'static,
334 )*
335 {
336 type FArgs<'a> = ($(&'a [<T $type_idx>],)*);
337 }
338
339 impl<'b, $( [<T $type_idx>], )* $( [<IG $type_idx>], )*> VecInputGuard<($( [<T $type_idx>], )*), markers::GroupedVariables>
340 for ($( [<IG $type_idx>], )*)
341 where
342 $(
343 [<T $type_idx>]: 'static,
344 [<IG $type_idx>]: Deref<Target = [<T $type_idx>]>,
345 )*
346 {
347 fn as_input_value<'a>(&'a self) -> VecFnArg<'a, ($( [<T $type_idx>], )*), markers::GroupedVariables> {
348 ($(self.$type_idx.deref(), )*)
349 }
350 }
351
352
353 impl<$( [<T $type_idx>], )* $([<IRT $type_idx>], )*> VecInputReader<($( [<T $type_idx>], )*), markers::GroupedVariables> for ($([<IRT $type_idx>], )*)
354 where
355 $(
356 [<T $type_idx>]: Send + Sync + 'static,
357 [<IRT $type_idx>]: InputReader<[<T $type_idx>]>,
358 for<'a> <[<IRT $type_idx>] as InputReader<[<T $type_idx>]>>::InputGuard<'a>: Deref<Target = [<T $type_idx>]>,
359 )*
360 {
361 fn read_vec_input(&self) -> Box<dyn VecInputGuard<($( [<T $type_idx>], )*), markers::GroupedVariables> + '_> {
362 Box::new(
363 ($(
364 self.$type_idx.read_input(),
365 )*)
366 )
367 }
368 }
369 }
370 };
371}
372
373macro_rules! computation_builder_reversed {
374 ({} {$($reversed:tt),*}) => {
375 computation_builder!($($reversed),*);
376 };
377 ({$first:tt $(, $rest:tt)*} {$($reversed:tt),*}) => {
378 computation_builder_reversed!({$($rest),*} {$first $(, $reversed)*}); };
380}
381
382macro_rules! computation_builders {
383 ($first_type_idx: tt) => {
384 computation_builder!($first_type_idx);
385 };
386 ($first_type_idx: tt, $($type_idx: tt),*) => {
387 computation_builder_reversed!({$($type_idx),*} {$first_type_idx});
388 computation_builders!($($type_idx),*);
389 }
390}
391computation_builders!(20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
392
393impl<'b, T, Marker> ComputationVecBuilder<T, Marker> for ()
394where
395 T: Sync + Send + 'static,
396{
397 fn prepare(
398 &self,
399 _: &Arc<Dependency>,
400 ) -> LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>> {
401 Default::default()
402 }
403}
404
405impl<T, VT> ComputationBuilder<T> for Vec<&VT>
406where
407 VT: ComputationInputInterface<Type = T>,
408 T: Sync + Send + 'static,
409 for<'a> <<VT as ComputationInputInterface>::InputReaderType as InputReader<T>>::InputGuard<'a>:
410 Deref<Target = T>,
411{
412 type FunctorArgument<'a> = Vec<&'a VT::Type>;
413 fn prepare<'b>(
414 &self,
415 dependency: &Arc<Dependency>,
416 formula: impl for<'a> Fn(Self::FunctorArgument<'a>) -> T + 'b + Send + Sync,
417 ) -> impl Fn() -> T + 'b + Send + Sync {
418 let variables = <Vec<&VT> as ComputationVecBuilder<T, DefaultVariableMarker>>::prepare(
419 self, dependency,
420 );
421
422 move || {
423 let unlocked_vars: Vec<_> = variables.iter().map(|(_, v)| v.read_vec_input()).collect();
424 let values: Vec<&T> = unlocked_vars
425 .iter()
426 .map(|uv| -> &T { uv.as_input_value() })
427 .collect();
428 formula(values)
429 }
430 }
431}
432impl<T, VT, Marker> ComputationVecBuilder<T, Marker> for Vec<&VT>
433where
434 VT: ComputationInputInterface<Type = T>,
435 T: Sync + Send + 'static,
436 VecComputationFArgsSelector<T, Marker>: VecComputationFArgsSelectorTrait,
437 <VT as ComputationInputInterface>::InputReaderType: VecInputReader<T, Marker>,
438{
439 fn prepare(
440 &self,
441 dependency: &Arc<Dependency>,
442 ) -> LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>> {
443 self.into_iter()
444 .map(|v| {
445 let (getter, v_dependency) = v.prepare_value();
446 let id = v_dependency.key.clone();
447 Dependency::link(&dependency, v_dependency);
448
449 let vm: Box<dyn VecInputReader<T, Marker>> = Box::new(getter);
450 (id, vm)
451 })
452 .collect()
453 }
454}
455
456struct ComputationData<T>
462where
463 T: Send + Sync + 'static,
464{
465 result: ArcRwLock<T>,
466 formula: ArcMutex<Box<dyn Fn() -> T + Sync + Send + 'static>>,
467 dependency: Arc<Dependency>,
468}
469
470impl<T> Debug for ComputationData<T>
471where
472 T: Debug + Sync + Send + 'static,
473{
474 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
475 f.debug_struct("").field("result", &self.result).finish()
476 }
477}
478
479impl<T> Clone for ComputationData<T>
480where
481 T: Send + Sync + 'static,
482{
483 fn clone(&self) -> Self {
484 Self {
485 result: self.result.clone(),
486 formula: self.formula.clone(),
487 dependency: self.dependency.clone(),
488 }
489 }
490}
491
492#[derive(Debug)]
536pub struct Computation<T>
537where
538 T: Send + Sync + 'static,
539{
540 data: ComputationData<T>,
541}
542
543impl<T> ComputationValueType for Computation<T>
544where
545 T: Send + Sync + 'static,
546{
547 type Type = T;
548}
549
550impl<T> ComputationInputInterface for Computation<T>
551where
552 T: Send + Sync + 'static,
553{
554 type InputReaderType = ComputationData<T>;
555 fn id(&self) -> Key {
556 self.data.dependency.key.clone()
557 }
558 fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
559 (self.data.clone(), self.data.dependency.clone())
560 }
561}
562
563impl<T> InputReader<T> for ComputationData<T>
564where
565 T: Sync + Send + 'static,
566{
567 type InputGuard<'a> = RwLockReadGuard<'a, T>;
568 fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
569 if self
570 .dependency
571 .outdated
572 .load(std::sync::atomic::Ordering::Relaxed)
573 {
574 self.dependency
575 .outdated
576 .store(false, std::sync::atomic::Ordering::Relaxed);
577 *self.result.write().unwrap() = (self.formula.lock().unwrap())();
578 }
579 self.result.read().unwrap()
580 }
581}
582
583impl<T> Computation<T>
584where
585 T: Sync + Send + 'static,
586{
587 pub fn new<TVars>(
589 formula: impl for<'a> Fn(TVars::FunctorArgument<'a>) -> T + 'static + Send + Sync,
590 tvars: TVars,
591 ) -> Self
592 where
593 TVars: ComputationBuilder<T>,
594 {
595 let dependency = Dependency::new();
596
597 let formula = tvars.prepare(&dependency, formula);
598 let result = arc_rw_lock_new((formula)());
599 Self {
600 data: ComputationData::<T> {
601 result,
602 formula: arc_mutex_new(Box::new(formula)),
603 dependency,
604 },
605 }
606 }
607 pub fn read_result<'a>(&'a self) -> impl Deref<Target = T> + 'a {
609 self.data.read_input()
610 }
611}
612
613pub trait VecComputationFArgsSelectorTrait {
623 type FArgs<'a>;
625}
626
627pub struct VecComputationFArgsSelector<C, Marker> {
630 first_casper: PhantomData<C>,
631 second_casper: PhantomData<Marker>,
632}
633
634impl<C> VecComputationFArgsSelectorTrait for VecComputationFArgsSelector<C, DefaultVariableMarker>
635where
636 C: 'static,
637{
638 type FArgs<'a> = &'a C;
639}
640
641pub mod markers {
643 #[derive(Debug)]
645 pub struct IndividualVariable {}
646
647 #[derive(Debug)]
649 pub struct GroupedVariables {}
650}
651
652type DefaultVariableMarker = markers::IndividualVariable;
654
655type VecFnArg<'a, C, Marker> =
656 <VecComputationFArgsSelector<C, Marker> as VecComputationFArgsSelectorTrait>::FArgs<'a>;
657type VecFnArgs<'a, C, Marker> = Vec<VecFnArg<'a, C, Marker>>;
658
659struct VecComputationData<T, C, Marker>
660where
661 T: Send + Sync + 'static,
662 C: Send + Sync + 'static,
663 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
664{
665 result: ArcRwLock<T>,
666 variables: ArcRwLock<LinkedHashMap<Key, Box<dyn VecInputReader<C, Marker>>>>,
667 formula: ArcMutex<Box<dyn for<'a> Fn(VecFnArgs<'a, C, Marker>) -> T + Send + Sync>>,
668 dependency: Arc<Dependency>,
669}
670
671impl<T, C, Marker> Debug for VecComputationData<T, C, Marker>
672where
673 T: Send + Sync + 'static + Debug,
674 C: Send + Sync + 'static + Debug,
675 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
676{
677 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
678 f.debug_struct("")
679 .field("result", &self.result)
680 .field("dependency", &self.dependency)
681 .finish()
682 }
683}
684
685impl<T, C, Marker> Clone for VecComputationData<T, C, Marker>
686where
687 T: Send + Sync + 'static,
688 C: Send + Sync + 'static,
689 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
690{
691 fn clone(&self) -> Self {
692 Self {
693 result: self.result.clone(),
694 variables: self.variables.clone(),
695 formula: self.formula.clone(),
696 dependency: self.dependency.clone(),
697 }
698 }
699}
700
701impl<T, C, Marker> InputReader<T> for VecComputationData<T, C, Marker>
702where
703 T: Sync + Send + 'static,
704 C: Send + Sync + 'static,
705 Marker: 'static,
706 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
707{
708 type InputGuard<'a> = RwLockReadGuard<'a, T>;
709 fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
710 if self
711 .dependency
712 .outdated
713 .load(std::sync::atomic::Ordering::Relaxed)
714 {
715 self.dependency
716 .outdated
717 .store(false, std::sync::atomic::Ordering::Relaxed);
718 let variables = self.variables.read().unwrap();
719 let unlocked_vars: Vec<_> = variables.iter().map(|(_, v)| v.read_vec_input()).collect();
720 let values: VecFnArgs<'_, C, Marker> = unlocked_vars
721 .iter()
722 .map(|uv| -> VecFnArg<'_, C, Marker> { uv.as_input_value() })
723 .collect();
724 *self.result.write().unwrap() = (self.formula.lock().unwrap())(values);
725 }
726 self.result.read().unwrap()
727 }
728}
729
730#[derive(Debug)]
771pub struct VecComputation<T, C = T, Marker = DefaultVariableMarker>
772where
773 T: Send + Sync + 'static,
774 C: Send + Sync + 'static,
775 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
776{
777 data: VecComputationData<T, C, Marker>,
778 casper: PhantomData<Marker>,
779}
780
781impl<T, C, Marker> ComputationValueType for VecComputation<T, C, Marker>
782where
783 T: Send + Sync + 'static,
784 C: Send + Sync + 'static,
785 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
786{
787 type Type = T;
788}
789
790impl<T, C, Marker> ComputationInputInterface for VecComputation<T, C, Marker>
791where
792 T: Send + Sync + 'static,
793 C: Send + Sync + 'static,
794 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait + 'static,
795{
796 type InputReaderType = VecComputationData<T, C, Marker>;
797 fn id(&self) -> Key {
798 self.data.dependency.key.clone()
799 }
800 fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
801 (self.data.clone(), self.data.dependency.clone())
802 }
803}
804
805impl<T, C, Marker> VecComputation<T, C, Marker>
806where
807 T: Send + Sync + 'static,
808 C: Send + Sync + 'static,
809 Marker: 'static,
810 VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
811{
812 pub fn new<TVars>(
814 formula: impl for<'a> Fn(VecFnArgs<'a, C, Marker>) -> T + 'static + Send + Sync,
815 tvars: TVars,
816 ) -> Self
817 where
818 TVars: ComputationVecBuilder<C, Marker>,
819 {
820 let dependency = Dependency::new();
821 let variables = tvars.prepare(&dependency);
822
823 let result = arc_rw_lock_new({
824 let unlocked_vars: Vec<_> = variables.iter().map(|(_, v)| v.read_vec_input()).collect();
825 let values: VecFnArgs<'_, C, Marker> = unlocked_vars
826 .iter()
827 .map(|uv| -> VecFnArg<'_, C, Marker> { uv.as_input_value() })
828 .collect();
829 (formula)(values)
830 });
831 let variables = arc_rw_lock_new(variables);
832
833 Self {
834 data: VecComputationData::<T, C, Marker> {
835 result,
836 variables,
837 formula: arc_mutex_new(Box::new(formula)),
838 dependency,
839 },
840 casper: Default::default(),
841 }
842 }
843 pub fn read_result<'a>(&'a self) -> impl Deref<Target = T> + 'a {
845 self.data.read_input()
846 }
847 pub fn push<CII>(&mut self, var: &CII)
849 where
850 CII: ComputationInputInterface<Type = C>,
851 <CII as ComputationInputInterface>::InputReaderType: VecInputReader<C, Marker>,
852 {
853 let (getter, dep) = var.prepare_value();
854 let id = dep.key.clone();
855 Dependency::link(&self.data.dependency, dep);
856 self.data
857 .variables
858 .write()
859 .unwrap()
860 .insert(id, Box::new(getter));
861 self.data.dependency.notify_all();
862 }
863 pub fn remove(&mut self, var: &impl ComputationInputInterface) {
865 let id = var.id();
866 self.data.variables.write().unwrap().remove(&id);
867 self.data.dependency.remove_dependency(&id);
868 self.data.dependency.notify_all();
869 }
870}
871
872impl<T, C> VecComputation<T, C>
873where
874 T: Default + std::ops::Add<Output = T> + Sync + Send,
875 C: Into<T> + Clone + Sync + Send,
876{
877 pub fn sum<TVars>(tvars: TVars) -> Self
879 where
880 TVars: ComputationVecBuilder<C, DefaultVariableMarker>,
881 {
882 Self::new(
883 |a| {
884 a.iter()
885 .fold(T::default(), |a, b| a + <C as Into<T>>::into((**b).clone()))
886 as T
887 },
888 tvars,
889 )
890 }
891}
892
893impl<T, C> VecComputation<T, C>
894where
895 T: Default + for<'a> std::ops::Add<&'a T, Output = T> + Sync + Send,
896 for<'a> &'a C: Into<&'a T>,
897 C: Sync + Send,
898{
899 pub fn sum_ref<TVars>(tvars: TVars) -> Self
901 where
902 TVars: ComputationVecBuilder<C, DefaultVariableMarker>,
903 {
904 Self::new(
905 |a| {
906 a.iter()
907 .fold(T::default(), |a, b| a + <&C as Into<&T>>::into(*b)) as T
908 },
909 tvars,
910 )
911 }
912}
913impl<T, C> VecComputation<T, C>
914where
915 T: Default
916 + std::ops::Add<Output = T>
917 + TryFrom<usize>
918 + std::ops::Div<Output = T>
919 + Sync
920 + Send,
921 C: Into<T> + Clone + Sync + Send,
922 <T as TryFrom<usize>>::Error: Debug,
923{
924 pub fn average<TVars>(tvars: TVars) -> Self
926 where
927 TVars: ComputationVecBuilder<C, DefaultVariableMarker>,
928 {
929 Self::new(
930 |a| {
931 a.iter()
932 .fold(T::default(), |a, b| a + <C as Into<T>>::into((**b).clone()))
933 / (<usize as TryInto<T>>::try_into(a.len()).expect("usize overflow"))
934 },
935 tvars,
936 )
937 }
938}
939
940#[cfg(feature = "serde")]
947fn serde_dependency_new() -> Arc<Dependency> {
948 Dependency::new()
949}
950
951#[derive(Debug)]
961#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
962pub struct Variable<T>
963where
964 T: Send + Sync,
965{
966 t: ArcRwLock<T>,
967 #[cfg_attr(feature = "serde", serde(skip, default = "serde_dependency_new"))]
968 dependency: Arc<Dependency>,
969}
970
971impl<T> Default for Variable<T>
972where
973 T: Default + Send + Sync,
974{
975 fn default() -> Self {
976 Self {
977 t: ArcRwLock::<T>::default(),
978 dependency: Dependency::new(),
979 }
980 }
981}
982
983impl<T> From<T> for Variable<T>
984where
985 T: Send + Sync,
986{
987 fn from(value: T) -> Self {
988 Self::new(value)
989 }
990}
991
992impl<T> ComputationValueType for Variable<T>
993where
994 T: Send + Sync + 'static,
995{
996 type Type = T;
997}
998impl<T> ComputationInputInterface for Variable<T>
999where
1000 T: Send + Sync + 'static,
1001{
1002 type InputReaderType = ArcRwLock<T>;
1003 fn id(&self) -> Key {
1004 self.dependency.key.clone()
1005 }
1006 fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
1007 (self.t.clone(), self.dependency.clone())
1008 }
1009}
1010
1011impl<T> Variable<T>
1012where
1013 T: Send + Sync,
1014{
1015 pub fn new(t: T) -> Self {
1017 Self {
1018 t: arc_rw_lock_new(t),
1019 dependency: Dependency::new(),
1020 }
1021 }
1022 pub fn set(&self, t: T) {
1024 *self.t.write().unwrap() = t;
1025 self.dependency.notify_all();
1026 }
1027 pub fn read_value(&self) -> RwLockReadGuard<'_, T> {
1029 self.t.read().unwrap()
1030 }
1031 fn read_result(&self) -> RwLockReadGuard<'_, T> {
1033 self.t.read().unwrap()
1034 }
1035 pub fn ro_value(&self) -> ccutils::sync::RoLock<T> {
1037 ccutils::sync::RoLock::new(&self.t)
1038 }
1039 pub fn update(&self, f: impl Fn(&mut T)) {
1041 f(&mut self.t.write().unwrap());
1042 self.dependency.notify_all();
1043 }
1044}
1045
1046struct ReferenceData<T>
1053where
1054 T: Send + Sync + 'static,
1055{
1056 getter: ArcRwLock<Box<dyn VecInputReader<T, DefaultVariableMarker>>>,
1057 variable: Key,
1058 dependency: Arc<Dependency>,
1059}
1060
1061impl<T> Debug for ReferenceData<T>
1062where
1063 T: Debug + Sync + Send + 'static,
1064{
1065 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1066 f.debug_struct("")
1067 .finish()
1069 }
1070}
1071
1072impl<T> Clone for ReferenceData<T>
1073where
1074 T: Send + Sync + 'static,
1075{
1076 fn clone(&self) -> Self {
1077 Self {
1078 getter: self.getter.clone(),
1079 variable: self.variable.clone(),
1080 dependency: self.dependency.clone(),
1081 }
1082 }
1083}
1084
1085#[derive(Debug)]
1105pub struct Reference<T>
1106where
1107 T: Send + Sync + 'static,
1108{
1109 data: ReferenceData<T>,
1110}
1111
1112impl<T> ComputationValueType for Reference<T>
1113where
1114 T: Send + Sync + 'static,
1115{
1116 type Type = T;
1117}
1118
1119impl<T> ComputationInputInterface for Reference<T>
1120where
1121 T: Send + Sync + 'static,
1122{
1123 type InputReaderType = ReferenceData<T>;
1124 fn id(&self) -> Key {
1125 self.data.dependency.key.clone()
1126 }
1127 fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
1128 (self.data.clone(), self.data.dependency.clone())
1129 }
1130}
1131
1132#[ouroboros::self_referencing]
1133struct Whatever<T>
1134where
1135 T: 'static,
1136{
1137 lock: ArcRwLock<Box<dyn VecInputReader<T, DefaultVariableMarker>>>,
1138 #[covariant]
1139 #[borrows(lock)]
1140 getter: RwLockReadGuard<'this, Box<dyn VecInputReader<T, DefaultVariableMarker>>>,
1141 #[covariant]
1142 #[borrows(getter)]
1143 guard: Box<dyn VecInputGuard<T, DefaultVariableMarker> + 'this>,
1144}
1145
1146impl<'a, T> Deref for Whatever<T>
1147where
1148 T: Sync + Send + 'static,
1149{
1150 type Target = T;
1151 fn deref(&self) -> &Self::Target {
1152 self.borrow_guard().as_input_value()
1153 }
1156}
1157
1158impl<T> InputReader<T> for ReferenceData<T>
1159where
1160 T: Sync + Send + 'static,
1161{
1162 type InputGuard<'a> = Whatever<T>;
1163 fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
1164 WhateverBuilder {
1165 lock: self.getter.clone(),
1166 getter_builder: |l| l.read().unwrap(),
1167 guard_builder: |l| l.read_vec_input(),
1168 }
1169 .build()
1170 }
1171}
1172
1173impl<T> Reference<T>
1174where
1175 T: Sync + Send + 'static,
1176{
1177 pub fn new<TVar>(tvar: &TVar) -> Self
1179 where
1180 TVar: ComputationInputInterface<Type = T>,
1181 for<'a> <<TVar as ComputationInputInterface>::InputReaderType as InputReader<T>>::InputGuard<'a>:
1182 Deref<Target = T>,
1183 {
1184 let dependency = Dependency::new();
1185 let (reader, dependent) = tvar.prepare_value();
1186 let variable = dependent.key.clone();
1187 Dependency::link(&dependency, dependent);
1188 Self {
1189 data: ReferenceData::<T> {
1190 getter: ccutils::sync::arc_rw_lock_new(Box::new(reader)),
1191 variable,
1192 dependency,
1193 },
1194 }
1195 }
1196 pub fn read_value<'a>(&'a self) -> impl Deref<Target = T> + 'a {
1198 self.data.read_input()
1199 }
1200 fn read_result<'a>(&'a self) -> impl Deref<Target = T> + 'a {
1201 self.data.read_input()
1202 }
1203 pub fn replace<TVar>(&mut self, tvar: &TVar)
1205 where
1206 TVar: ComputationInputInterface<Type = T>,
1207 for<'a> <<TVar as ComputationInputInterface>::InputReaderType as InputReader<T>>::InputGuard<'a>:
1208 Deref<Target = T>,
1209 {
1210 let (reader, dependent) = tvar.prepare_value();
1211 self.data.dependency.remove_dependency(&self.data.variable);
1212 self.data.variable = dependent.key.clone();
1213 Dependency::link(&self.data.dependency, dependent);
1214 *self.data.getter.write().unwrap() = Box::new(reader);
1215 self.data.dependency.notify_all();
1216 }
1217}
1218
1219macro_rules! generate_traits_for_computation_getters {
1227 ($name:tt $(, extra: [$($extra_t: tt),+])? $(, blob: [$where_left:ty : $where_right: tt])?) => {
1228 impl<T $($(, $extra_t)+)?> PartialEq for $name<T $($(, $extra_t)+)?>
1229 where
1230 T: PartialEq + Send + Sync,
1231 $($($extra_t: Send + Sync + 'static,)+)?
1232 $($where_left: $where_right)?
1233 {
1234 fn eq(&self, other: &Self) -> bool {
1235 self.read_result().eq(&other.read_result())
1236 }
1237 }
1238
1239 impl<T $($(, $extra_t)+)?> PartialOrd for $name<T $($(, $extra_t)+)?>
1240 where
1241 T: PartialOrd + Send + Sync,
1242 $($($extra_t: Send + Sync + 'static,)+)?
1243 $($where_left: $where_right)?
1244 {
1245 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1246 self.read_result().partial_cmp(&other.read_result())
1247 }
1248 }
1249
1250 impl<T $($(, $extra_t)+)?> PartialEq<T> for $name<T $($(, $extra_t)+)?>
1251 where
1252 T: PartialEq + Send + Sync,
1253 $($($extra_t: Send + Sync + 'static,)+)?
1254 $($where_left: $where_right)?
1255 {
1256 fn eq(&self, other: &T) -> bool {
1257 self.read_result().eq(other)
1258 }
1259 }
1260
1261 impl<T $($(, $extra_t)+)?> PartialOrd<T> for $name<T $($(, $extra_t)+)?>
1262 where
1263 T: PartialOrd + Send + Sync,
1264 $($($extra_t: Send + Sync + 'static,)+)?
1265 $($where_left: $where_right)?
1266 {
1267 fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
1268 self.read_result().partial_cmp(other)
1269 }
1270 }
1271 };
1272}
1273
1274generate_traits_for_computation_getters!(Computation);
1275generate_traits_for_computation_getters!(VecComputation, extra: [C, Marker], blob: [VecComputationFArgsSelector::<C, Marker>: VecComputationFArgsSelectorTrait]);
1276generate_traits_for_computation_getters!(Reference);
1277generate_traits_for_computation_getters!(Variable);
1278
1279#[cfg(test)]
1286mod tests {
1287 use super::*;
1288
1289 #[test]
1290 fn static_computation() {
1291 let v1 = Variable::<u32>::new(1);
1292 let v2 = Variable::<u32>::new(2);
1293 let v3 = Variable::<u32>::new(3);
1294
1295 let c1 = Computation::<u32>::new(|(a, b, c)| a + b + c, (&v1, &v2, &v3));
1296 assert_eq!(c1, 6);
1297
1298 v1.set(4);
1299 assert_eq!(c1, 9);
1300
1301 v3.update(|x| *x -= 3);
1302 assert_eq!(c1, 6);
1303 }
1304
1305 #[test]
1306 fn heterogenous_computation() {
1307 let v1 = Variable::<u16>::new(1);
1308 let v2 = Variable::<u32>::new(2);
1309 let v3 = Variable::<f32>::new(3.0);
1310
1311 let c1 = Computation::<f64>::new(
1312 |(a, b, c)| *a as f64 + *b as f64 + *c as f64,
1313 (&v1, &v2, &v3),
1314 );
1315 assert_eq!(c1, 6.0);
1316
1317 v1.set(4);
1318 assert_eq!(c1, 9.0);
1319
1320 v3.update(|x| *x -= 3.0);
1321 assert_eq!(c1, 6.0);
1322 }
1323
1324 #[test]
1325 fn intermediary_computation() {
1326 let v1 = Variable::<u16>::new(1);
1327 let v2 = Variable::<u32>::new(2);
1328 let v3 = Variable::<f32>::new(3.0);
1329
1330 let c1 = Computation::<f64>::new(
1331 |(a, b, c)| *a as f64 + *b as f64 + *c as f64,
1332 (&v1, &v2, &v3),
1333 );
1334 assert_eq!(c1, 6.0);
1335
1336 let v4 = Variable::<f64>::new(5.0);
1337
1338 let c2 = Computation::<f64>::new(|(a, b)| a + b, (&c1, &v4));
1339 assert_eq!(c2, 11.0);
1340
1341 v1.set(4);
1342 assert_eq!(c1, 9.0);
1343 assert_eq!(c2, 14.0);
1344
1345 v3.update(|x| *x -= 3.0);
1346 assert_eq!(c1, 6.0);
1347 assert_eq!(c2, 11.0);
1348
1349 v4.set(-1.0);
1350 assert_eq!(c1, 6.0);
1351 assert_eq!(c2, 5.0);
1352
1353 v1.set(0);
1354 assert_eq!(c2, 1.0);
1355 }
1356
1357 #[test]
1358 fn vec_computation() {
1359 let v1 = Variable::<u32>::new(1);
1360 let v2 = Variable::<u32>::new(2);
1361 let v3 = Variable::<u32>::new(3);
1362
1363 let mut c1 = VecComputation::<u32>::average(vec![&v1, &v2, &v3]);
1364 assert_eq!(c1, 2);
1365
1366 let v4 = Variable::<u32>::new(10);
1367 c1.push(&v4);
1368 assert_eq!(c1, 4);
1369 c1.remove(&v1);
1370 c1.remove(&v3);
1371 assert_eq!(c1, 6);
1372 v1.set(4);
1373 v3.set(2);
1374 assert_eq!(c1, 6);
1375 v4.set(2);
1376 assert_eq!(c1, 2);
1377 v2.set(0);
1378 assert_eq!(c1, 1);
1379
1380 let c2 = VecComputation::<u32>::sum(vec![&v1, &v2, &v3]);
1381 assert_eq!(c2, 6);
1382 }
1383
1384 #[test]
1385 fn vec_intermediary_computation() {
1386 let v1 = Variable::<u32>::new(1);
1387 let v2 = Variable::<u32>::new(2);
1388 let v3 = Variable::<u32>::new(3);
1389
1390 let mut c1 = VecComputation::<u32>::average(vec![&v1, &v2, &v3]);
1391 assert_eq!(c1, 2);
1392
1393 let v5 = Variable::<f32>::new(4.0);
1394 let c2 = Computation::<f32>::new(|(a, b)| *a as f32 + b, (&c1, &v5));
1395 assert_eq!(c2, 6.0);
1396
1397 let v6 = Variable::<f32>::new(2.0);
1398 let mut c3 = VecComputation::<f32>::sum((&c2, &v6));
1399
1400 let v4 = Variable::<u32>::new(10);
1401 c1.push(&v4);
1402 assert_eq!(c1, 4);
1403 assert_eq!(c2, 8.0);
1404 assert_eq!(c3, 10.0);
1405 c1.remove(&v1);
1406 c1.remove(&v3);
1407 assert_eq!(c1, 6);
1408 assert_eq!(c2, 10.0);
1409 assert_eq!(c3, 12.0);
1410 v1.set(4);
1411 v3.set(2);
1412 assert_eq!(c1, 6);
1413 assert_eq!(c2, 10.0);
1414 assert_eq!(c3, 12.0);
1415 v4.set(2);
1416 assert_eq!(c1, 2);
1417 assert_eq!(c2, 6.0);
1418 assert_eq!(c3, 8.0);
1419 v2.set(0);
1420 assert_eq!(c1, 1);
1421 assert_eq!(c2, 5.0);
1422 assert_eq!(c3, 7.0);
1423
1424 let v7 = Variable::<f32>::new(1.0);
1425 c3.push(&v7);
1426 assert_eq!(c1, 1);
1427 assert_eq!(c2, 5.0);
1428 assert_eq!(c3, 8.0);
1429 c3.remove(&v6);
1430 assert_eq!(c1, 1);
1431 assert_eq!(c2, 5.0);
1432 assert_eq!(c3, 6.0);
1433 c3.remove(&c2);
1434 assert_eq!(c1, 1);
1435 assert_eq!(c2, 5.0);
1436 assert_eq!(c3, 1.0);
1437 }
1438 #[test]
1439 fn test_traits() {
1440 let v1: Variable<i32> = 0.into();
1441 let v2: Variable<i32> = 1.into();
1442 let c1 = Computation::new(|(v1, v2)| *v1 + *v2, (&v1, &v2));
1443 let c2 = Computation::new(|(v1, v2)| *v1 - *v2, (&v1, &v2));
1444 let c3 = VecComputation::new(|v| *v[0] + *v[1], (&v1, &v2));
1445 let c4 = VecComputation::new(|v| *v[0] - *v[1], vec![&v1, &v2]);
1446 let c5 = VecComputation::new(|v| *v[0] - *v[1], (&v1, &v2));
1447 assert_eq!(c1, 1);
1448 assert_eq!(c2, -1);
1449 assert_eq!(c3, 1);
1450 assert_eq!(c4, -1);
1451 assert_eq!(c5, -1);
1452 assert!(v1 != v2);
1453 assert!(v1 < v2);
1454 assert!(c1 != c2);
1455 assert!(c1 > c2);
1456 assert!(c3 != c4);
1457 assert!(c3 > c4);
1458 assert!(c3 != c5);
1459 assert!(c3 > c5);
1460 assert!(c4 == c5);
1461 }
1462 #[test]
1463 fn test_vec_order() {
1464 let v1: Variable<i32> = 0.into();
1465 let v2: Variable<i32> = 1.into();
1466 let v3: Variable<i32> = 2.into();
1467 let v4: Variable<i32> = 3.into();
1468 let v5: Variable<i32> = 4.into();
1469 let v6: Variable<i32> = 5.into();
1470 let mut c1 = VecComputation::new(|v| v.windows(2).all(|w| w[0] < w[1]), (&v1, &v2));
1471 assert_eq!(c1, true);
1472 c1.push(&v3);
1473 c1.push(&v4);
1474 assert_eq!(c1, true);
1475 c1.remove(&v4);
1476 assert_eq!(c1, true);
1477 c1.push(&v5);
1478 assert_eq!(c1, true);
1479 c1.push(&v6);
1480 assert_eq!(c1, true);
1481 c1.remove(&v3);
1482 assert_eq!(c1, true);
1483 c1.remove(&v6);
1484 assert_eq!(c1, true);
1485 c1.push(&v4);
1486 assert_eq!(c1, false);
1487 c1.push(&v6);
1488 assert_eq!(c1, false);
1489 c1.remove(&v4);
1490 assert_eq!(c1, true);
1491 }
1492 #[test]
1493 fn test_tuples() {
1494 let v1: Variable<i32> = 0.into();
1495 let v2: Variable<i32> = 1.into();
1496 let v3: Variable<i32> = 2.into();
1497
1498 let mut c1 = VecComputation::<i32, (i32, i32, i32), markers::GroupedVariables>::new(
1499 |v: Vec<(&i32, &i32, &i32)>| v.into_iter().fold(0, |a, (b, c, d)| a + b + c + d),
1500 (&(&v1, &v2, &v3),),
1501 );
1502
1503 assert_eq!(c1, 3);
1504
1505 let v4: Variable<i32> = 3.into();
1506 let v5: Variable<i32> = 4.into();
1507 let v6: Variable<i32> = 5.into();
1508
1509 c1.push(&(&v4, &v5, &v6));
1510
1511 assert_eq!(c1, 15);
1512 }
1513 #[test]
1514 fn test_references() {
1515 let v1: Variable<i32> = 2.into();
1516 let v2: Variable<i32> = 1.into();
1517 let mut ref1 = Reference::<i32>::new(&v1);
1518 let c1 = Computation::<i32>::new(|(x,)| *x, (&ref1,));
1519 assert_eq!(c1, 2);
1520 v1.set(3);
1521 assert_eq!(c1, 3);
1522 ref1.replace(&v2);
1523 assert_eq!(c1, 1);
1524 v1.set(2);
1525 assert_eq!(ref1, 1);
1526 assert_eq!(c1, 1);
1527 v2.set(4);
1528 assert_eq!(ref1, 4);
1529 assert_eq!(c1, 4);
1530 }
1531}