cargo/util/
local_poll_adapter.rs1use crate::util::data_structures::HashMap;
2use futures::{FutureExt, future::LocalBoxFuture, stream::FuturesUnordered};
3use std::{hash::Hash, ops::Deref, task::Poll};
4
5pub struct LocalPollAdapter<'a, S, K, R> {
14 pool: FuturesUnordered<LocalBoxFuture<'a, (K, R)>>,
15 cache: HashMap<K, Poll<R>>,
16 self_parameter: S,
17}
18
19impl<'a, S, K, V, E> LocalPollAdapter<'a, S, K, Result<V, E>>
20where
21 S: Clone + Deref + 'a,
22 K: Clone + Hash + Eq + 'a,
23 V: Clone,
24{
25 pub fn new(self_parameter: S) -> Self {
26 Self {
27 pool: FuturesUnordered::new(),
28 cache: HashMap::default(),
29 self_parameter,
30 }
31 }
32
33 pub fn poll<F>(&mut self, f: F, key: K) -> Poll<Result<V, E>>
41 where
42 F: AsyncFn(&S::Target, &K) -> Result<V, E> + 'a,
43 {
44 match self.cache.get(&key) {
45 Some(Poll::Ready(Ok(v))) => return Poll::Ready(Ok(v.clone())),
47 Some(Poll::Ready(Err(_))) => return self.cache.remove(&key).unwrap(),
50 Some(Poll::Pending) => return Poll::Pending,
52 None => {}
54 }
55
56 let mut future = {
59 let key = key.clone();
60 let self_parameter = self.self_parameter.clone();
61 async move {
62 let v = f(self_parameter.deref(), &key).await;
63 (key, v)
64 }
65 .boxed_local()
66 };
67
68 if let Some((k, v)) = (&mut future).now_or_never() {
71 if let Ok(success) = &v {
72 self.cache.insert(k, Poll::Ready(Ok(success.clone())));
74 }
75 return Poll::Ready(v);
76 }
77
78 self.cache.insert(key.clone(), Poll::Pending);
80
81 self.pool.push(future);
83 Poll::Pending
84 }
85
86 pub fn pending_count(&self) -> usize {
88 self.pool.len()
89 }
90
91 pub fn wait(&mut self) -> bool {
93 let is_empty = self.pool.is_empty();
94 for (k, v) in crate::util::block_on_stream(&mut self.pool) {
95 *self
96 .cache
97 .get_mut(&k)
98 .expect("all pending work is in the cache") = Poll::Ready(v);
99 }
100 is_empty
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::LocalPollAdapter;
107 use std::{rc::Rc, task::Poll};
108
109 fn yield_once() -> impl std::future::Future<Output = ()> {
111 let mut yielded = false;
112
113 std::future::poll_fn(move |cx| {
114 if yielded {
115 Poll::Ready(())
116 } else {
117 yielded = true;
118 cx.waker().wake_by_ref();
119 Poll::Pending
120 }
121 })
122 }
123
124 struct Thing {}
125
126 impl Thing {
127 async fn widen(&self, i: &i32) -> Result<i64, ()> {
128 if *i > 10 {
129 yield_once().await;
131 }
132 if *i % 2 != 0 {
133 return Err(());
135 }
136 Ok(*i as i64)
137 }
138 }
139
140 struct PolledThing<'a> {
142 poller: LocalPollAdapter<'a, Rc<Thing>, i32, Result<i64, ()>>,
143 }
144
145 impl<'a> PolledThing<'a> {
146 fn new() -> Self {
147 Self {
148 poller: LocalPollAdapter::new(Rc::new(Thing {})),
149 }
150 }
151
152 fn widen(&mut self, i: &i32) -> Poll<Result<i64, ()>> {
154 self.poller.poll(Thing::widen, i.clone())
155 }
156
157 fn wait(&mut self) -> bool {
158 self.poller.wait()
159 }
160 }
161
162 #[test]
163 fn immediate_success() {
164 let mut p = PolledThing::new();
165 assert_eq!(p.widen(&2), Poll::Ready(Ok(2)));
166 assert!(p.wait());
167 }
168
169 #[test]
170 fn immediate_error() {
171 let mut p = PolledThing::new();
172 assert_eq!(p.widen(&1), Poll::Ready(Err(())));
173 assert!(p.wait());
174 }
175
176 #[test]
177 fn deferred_error() {
178 let mut p = PolledThing::new();
179 assert_eq!(p.widen(&1001), Poll::Pending);
180 assert!(!p.wait());
181 assert_eq!(p.widen(&1001), Poll::Ready(Err(())));
182 assert!(p.wait());
183 assert_eq!(p.widen(&1001), Poll::Pending);
185 assert!(!p.wait());
186 assert_eq!(p.widen(&1001), Poll::Ready(Err(())));
187 assert!(p.wait());
188 }
189
190 #[test]
191 fn deferred_success() {
192 let mut p = PolledThing::new();
193 assert_eq!(p.widen(&50), Poll::Pending);
194 assert!(!p.wait());
195 assert_eq!(p.widen(&50), Poll::Ready(Ok(50)));
196 assert!(p.wait());
197 assert_eq!(p.widen(&50), Poll::Ready(Ok(50)));
199 assert!(p.wait());
200 }
201}