Skip to content

Commit 2ffae9d

Browse files
committed
add Executor::run_with_local
Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
1 parent c1f0ac0 commit 2ffae9d

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/lib.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,55 @@ impl Executor {
193193
}
194194
})
195195
}
196+
197+
/// Runs a local executor and the multi-threaded one until the given future completes.
198+
///
199+
/// # Examples
200+
///
201+
/// ```
202+
/// use async_executor::{Executor, Task};
203+
///
204+
/// let ex = Executor::new();
205+
///
206+
/// let task = ex.spawn(async { 1 + 2 });
207+
/// let res = ex.run_with_local(async {
208+
/// let local = Task::local(async { 1 + 1 });
209+
/// task.await * local.await
210+
/// });
211+
///
212+
/// assert_eq!(res, 6);
213+
/// ```
214+
pub fn run_with_local<T>(&self, future: impl Future<Output = T>) -> T {
215+
let local_executor = LocalExecutor::new();
216+
LOCAL_EX.set(&local_executor, || {
217+
self.enter(|| {
218+
let (p, u) = parking::pair();
219+
220+
let ticker = self.ex.ticker({
221+
let u = u.clone();
222+
move || u.unpark()
223+
});
224+
225+
pin!(future);
226+
let waker = waker_fn(move || u.unpark());
227+
let cx = &mut Context::from_waker(&waker);
228+
229+
'start: loop {
230+
if let Poll::Ready(t) = future.as_mut().poll(cx) {
231+
break t;
232+
}
233+
234+
for _ in 0..200 {
235+
if !ticker.tick() && !local_executor.ex.tick() {
236+
p.park();
237+
continue 'start;
238+
}
239+
}
240+
p.park_timeout(Duration::from_secs(0));
241+
}
242+
})
243+
})
244+
}
196245
}
197246

198247
impl Default for Executor {

0 commit comments

Comments
 (0)