standing_relations/feedback/
context.rs1use std::{
2 cell::RefCell,
3 hash::Hash,
4 ops::{Deref, DerefMut},
5 rc::Rc,
6 sync::{Arc, RwLock},
7};
8
9use crate::{
10 core::{
11 self,
12 pipes::{self, Receiver, Sender},
13 TrackingIndex,
14 },
15 Input, InputRelation,
16};
17
18use self::{
19 input_change_tracker::{InputChangeTracker, IsInputChangeTracker},
20 pq_receiver::PQReceiver,
21};
22
23use super::op::{Instruct, IsFeedback, IsFeeder};
24
25pub use self::tracker::ContextTracker;
26
27mod input_change_tracker;
28mod pq_receiver;
29mod tracker;
30
31pub struct CreationContext<'a, I = ()> {
32 inner: core::CreationContext<'a>,
33 feeders: Vec<Box<dyn IsFeeder<'a, I> + 'a>>,
34 input_trackers: Vec<Rc<RefCell<dyn IsInputChangeTracker<I> + 'a>>>,
35 extra_edges: Arc<RwLock<Vec<(TrackingIndex, TrackingIndex)>>>,
36 dirty_send: Sender<usize>,
37 dirty_receive: Receiver<usize>,
38}
39
40impl<I> Default for CreationContext<'_, I> {
41 fn default() -> Self {
42 let (dirty_send, dirty_receive) = pipes::new();
43 Self {
44 inner: Default::default(),
45 feeders: Default::default(),
46 input_trackers: Default::default(),
47 extra_edges: Default::default(),
48 dirty_send,
49 dirty_receive,
50 }
51 }
52}
53
54pub struct ExecutionContext<'a, I = ()> {
55 inner: core::ExecutionContext<'a>,
56 feeders: Vec<Box<dyn IsFeeder<'a, I> + 'a>>,
57 input_trackers: Vec<Rc<RefCell<dyn IsInputChangeTracker<I> + 'a>>>,
58 extra_edges: Arc<RwLock<Vec<(TrackingIndex, TrackingIndex)>>>,
59 dirty: PQReceiver,
60}
61
62impl<'a, I> ExecutionContext<'a, I> {
63 pub fn commit(&mut self) -> Option<I> {
64 loop {
65 self.inner.commit();
66 match self.dirty.pop_min() {
67 Some(feeder_index) => match self.feeders[feeder_index].feed(&self.inner) {
68 Instruct::Unchanged => (),
69 Instruct::Changed => self.dirty.insert(feeder_index),
70 Instruct::Interrupt(interrupted) => return Some(interrupted),
71 },
72 None => return None,
73 }
74 }
75 }
76 pub fn tracker(&self) -> ContextTracker {
77 ContextTracker::new(self.inner.tracker().clone(), self.extra_edges.clone())
78 }
79 pub fn in_frame<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
80 for input_tracker in self.input_trackers.iter() {
81 input_tracker.borrow_mut().push_frame();
82 }
83 let result = f(self);
84 for input_tracker in self.input_trackers.iter() {
85 input_tracker.borrow_mut().pop_frame(self);
86 }
87 result
88 }
89}
90
91impl<'a, I> CreationContext<'a, I> {
92 pub fn new_() -> Self {
93 Default::default()
94 }
95 pub fn new_trackable_input<D: Eq + Hash + Clone + 'a>(
96 &mut self,
97 ) -> (Input<'a, D>, InputRelation<D>) {
98 let (mut input, relation) = self.inner.new_input_::<(D, isize)>();
99 let tracker: Rc<RefCell<InputChangeTracker<D>>> =
100 Rc::new(RefCell::new(InputChangeTracker::new(input.clone())));
101 {
102 let tracker = Rc::clone(&tracker);
103 input.add_listener(&self.inner, move |kvs| {
104 tracker.borrow_mut().add_changes(kvs)
105 });
106 }
107 self.input_trackers.push(tracker);
108 (input, relation)
109 }
110 pub fn begin(self) -> ExecutionContext<'a, I> {
111 ExecutionContext {
112 inner: self.inner.begin(),
113 feeders: self.feeders,
114 input_trackers: self.input_trackers,
115 extra_edges: self.extra_edges,
116 dirty: PQReceiver::new(self.dirty_receive),
117 }
118 }
119 pub(super) fn add_feeder(
120 &mut self,
121 mut feeder: impl IsFeedback<'a, I> + 'a,
122 extra_edge: Option<(TrackingIndex, TrackingIndex)>,
123 ) {
124 let mut dirty_send = self.dirty_send.clone();
125 let i = self.feeders.len();
126 feeder.add_listener(self, move || dirty_send.send(i));
127 self.feeders.push(Box::new(feeder));
128 if let Some(edge) = extra_edge {
129 self.extra_edges.write().unwrap().push(edge);
130 }
131 }
132 pub fn tracker(&self) -> ContextTracker {
133 ContextTracker::new(self.inner.tracker().clone(), self.extra_edges.clone())
134 }
135}
136
137impl<'a, I> Deref for CreationContext<'a, I> {
138 type Target = core::CreationContext<'a>;
139
140 fn deref(&self) -> &Self::Target {
141 &self.inner
142 }
143}
144
145impl<'a, I> DerefMut for CreationContext<'a, I> {
146 fn deref_mut(&mut self) -> &mut Self::Target {
147 &mut self.inner
148 }
149}
150
151impl<'a, I> Deref for ExecutionContext<'a, I> {
152 type Target = core::ExecutionContext<'a>;
153
154 fn deref(&self) -> &Self::Target {
155 &self.inner
156 }
157}
158
159impl<'a, I> DerefMut for ExecutionContext<'a, I> {
160 fn deref_mut(&mut self) -> &mut Self::Target {
161 &mut self.inner
162 }
163}