1use alloc::{
2 sync::{Arc, Weak},
3 vec::Vec,
4};
5use by_address::ByAddress;
6use core::{cmp::min, time::Duration};
7use owner_monad::OwnerMut;
8use raii_map::set::{insert, Set, SetHandle};
9
10use super::{
11 handle_event, time_since_start, Event, EventHandle, GenericSleep, Instant, Mutex, Selectable,
12};
13use crate::select_merge;
14
15type ContextValue = (Option<Instant>, Mutex<Option<ContextData>>);
16
17#[derive(Clone)]
18#[repr(transparent)]
19pub struct Context(Arc<ContextValue>);
37
38impl Context {
39 #[inline]
40 pub fn new_global() -> Self {
43 Self::new_internal(&[], None)
44 }
45
46 #[inline]
47 pub fn cancel(&self) {
49 cancel(&self.0.as_ref().1);
50 }
51
52 pub fn done(&'_ self) -> impl Selectable + '_ {
56 struct ContextSelect<'a>(&'a Context, EventHandle<ContextHandle>);
57
58 impl<'a> Selectable for ContextSelect<'a> {
59 fn poll(self) -> Result<(), Self> {
60 let mut lock = self.0 .0 .1.lock();
61 let opt = &mut lock.as_mut();
62 if opt.is_some() {
63 if self.0 .0 .0.map_or(false, |v| v <= time_since_start()) {
64 opt.take();
65 Ok(())
66 } else {
67 Err(self)
68 }
69 } else {
70 Ok(())
71 }
72 }
73 fn sleep(&self) -> GenericSleep {
74 GenericSleep::NotifyTake(self.0 .0 .0)
75 }
76 }
77
78 ContextSelect(self, handle_event(ContextHandle(Arc::downgrade(&self.0))))
79 }
80
81 pub fn wrap<'a, T: 'a>(
85 &'a self,
86 event: impl Selectable<T> + 'a,
87 ) -> impl Selectable<Option<T>> + 'a {
88 select_merge! {
89 r = event => Some(r),
90 _ = self.done() => None,
91 }
92 }
93
94 fn new_internal(parents: &[&Self], mut deadline: Option<Instant>) -> Self {
95 deadline = parents
96 .iter()
97 .filter_map(|parent| parent.0 .0)
98 .min()
99 .map_or(deadline, |d1| Some(deadline.map_or(d1, |d2| min(d1, d2))));
100 let ctx = Self(Arc::new((deadline, Mutex::new(None))));
101 let mut parent_handles = Vec::new();
102 parent_handles.reserve_exact(parents.len());
103 for parent in parents {
104 if let Some(handle) = insert(
105 ContextHandle(Arc::downgrade(&parent.0)),
106 ctx.0.clone().into(),
107 ) {
108 parent_handles.push(handle);
109 } else {
110 return ctx;
111 }
112 }
113 *ctx.0 .1.lock() = Some(ContextData {
114 _parents: parent_handles,
115 event: Event::new(),
116 children: Set::new(),
117 });
118 ctx
119 }
120}
121
122pub trait ParentContext {
125 fn fork(&self) -> Context;
127
128 fn fork_with_deadline(&self, deadline: Instant) -> Context;
132
133 fn fork_with_timeout(&self, timeout: Duration) -> Context {
137 self.fork_with_deadline(time_since_start() + timeout)
138 }
139}
140
141impl ParentContext for Context {
142 #[inline]
143 fn fork(&self) -> Context {
144 [self].fork()
145 }
146
147 #[inline]
148 fn fork_with_deadline(&self, deadline: Instant) -> Context {
149 [self].fork_with_deadline(deadline)
150 }
151}
152
153impl ParentContext for [&Context] {
154 #[inline]
155 fn fork(&self) -> Context {
156 Context::new_internal(self, None)
157 }
158
159 #[inline]
160 fn fork_with_deadline(&self, deadline: Instant) -> Context {
161 Context::new_internal(self, Some(deadline))
162 }
163}
164
165struct ContextData {
166 _parents: Vec<SetHandle<ByAddress<Arc<ContextValue>>, ContextHandle>>,
167 event: Event,
168 children: Set<ByAddress<Arc<ContextValue>>>,
169}
170
171impl Drop for ContextData {
172 fn drop(&mut self) {
173 self.event.notify();
174 for child in self.children.iter() {
175 cancel(&child.1)
176 }
177 }
178}
179
180struct ContextHandle(Weak<ContextValue>);
181
182impl OwnerMut<Event> for ContextHandle {
183 fn with<'a, U>(&'a mut self, f: impl FnOnce(&mut Event) -> U) -> Option<U>
184 where
185 Event: 'a,
186 {
187 Some(f(&mut self.0.upgrade()?.as_ref().1.lock().as_mut()?.event))
188 }
189}
190
191impl OwnerMut<Set<ByAddress<Arc<ContextValue>>>> for ContextHandle {
192 fn with<'a, U>(
193 &'a mut self,
194 f: impl FnOnce(&mut Set<ByAddress<Arc<ContextValue>>>) -> U,
195 ) -> Option<U>
196 where
197 ContextValue: 'a,
198 {
199 Some(f(&mut self
200 .0
201 .upgrade()?
202 .as_ref()
203 .1
204 .lock()
205 .as_mut()?
206 .children))
207 }
208}
209
210fn cancel(m: &Mutex<Option<ContextData>>) {
211 m.lock().take();
212}
213
214pub struct ContextWrapper(Option<Context>);
217
218impl ContextWrapper {
219 #[inline]
220 pub fn new() -> Self {
222 Self(None)
223 }
224
225 pub fn current(&self) -> Option<&Context> {
227 self.0.as_ref()
228 }
229
230 pub fn replace(&mut self) -> Context {
233 if let Some(ctx) = self.0.take() {
234 ctx.cancel();
235 }
236 let ctx = Context::new_global();
237 self.0 = Some(ctx.clone());
238 ctx
239 }
240
241 pub fn replace_ext(&mut self, ctx: impl ParentContext) -> Context {
244 if let Some(ctx) = self.0.take() {
245 ctx.cancel();
246 }
247 let ctx = ctx.fork();
248 self.0 = Some(ctx.clone());
249 ctx
250 }
251}
252
253impl Default for ContextWrapper {
254 #[inline]
255 fn default() -> Self {
256 Self::new()
257 }
258}