async_core/
runtime.rs

1extern crate alloc;
2
3use crate::BoxFuture;
4use alloc::boxed::Box;
5use core::future::Future;
6use core::ops::Deref;
7use core::pin::Pin;
8use core::task::{Context, Poll};
9use core::time::Duration;
10
11/// Stable wrapper of `!` type for the Stop struct.
12pub enum Never {}
13impl Never { pub fn into(self) -> ! { loop {} } }
14
15/// A never-completing future, used in stopping the runtime. Returns stable equivalent of `!`
16pub struct Stop;
17
18impl Future for Stop {
19    type Output = Never;
20
21    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
22        Poll::Pending // Return access to the runtime immediately
23    }
24}
25
26/// Future equivalent of a join handle
27pub struct SpawnedFuture<'a>(u64, &'a mut dyn InternalRuntime);
28
29impl<'a> Future for SpawnedFuture<'a> {
30    type Output = ();
31
32    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
33        let me = self.get_mut();
34        if me.1.contains(me.0) {
35            Poll::Pending
36        } else {
37            Poll::Ready(())
38        }
39    }
40}
41
42/// Trait to be implemented by async runtimes
43pub trait InternalRuntime {
44    /// Adds a new future to the queue to be completed.
45    fn push_boxed(&mut self, future: BoxFuture<'static, ()>) -> u64;
46    /// Returns if a future by some ID is still running.
47    fn contains(&mut self, id: u64) -> bool;
48    /// Asynchronously sleeps
49    fn sleep<'a>(&self, duration: Duration) -> BoxFuture<'a, ()>;
50    /// Stops the runtime
51    fn stop(&mut self) -> Stop;
52}
53/// Auto-trait with the methods that will actually be called by the users of the runtime.
54pub trait Runtime<'a> {
55    /// Adds a new future to the queue to be completed.
56    fn push(&mut self, future: impl Future<Output = ()> + 'static) {
57        Runtime::push_boxed(self, Box::pin(future))
58    }
59    /// Adds a new future to the queue to be completed.
60    fn push_boxed(&mut self, future: BoxFuture<'static, ()>);
61
62    /// Adds a new future to the queue to be completed and returns a future waiting for the added
63    /// future's completion.
64    fn spawn(&'a mut self, future: impl Future<Output = ()> + 'static) -> SpawnedFuture<'a> {
65        Runtime::spawn_boxed(self, Box::pin(future))
66    }
67    /// Adds a new future to the queue to be completed and returns a future waiting for the added
68    /// future's completion.
69    fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a>;
70
71    /// Asynchronously sleeps
72    fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()>;
73    /// Asynchronously sleeps some amount of milliseconds
74    fn sleep_ms<'b>(&'a self, amount: u64) -> BoxFuture<'b, ()> {
75        self.sleep(Duration::from_millis(amount))
76    }
77
78    /// Stops the runtime. This does not exit the process.
79    fn stop(&mut self) -> Stop;
80}
81
82/// Wrapper for anything that implements InternalRuntime, used to add a Runtime impl.
83pub struct RuntimeWrapper<'a>(pub(crate) &'a mut dyn InternalRuntime);
84
85/// Owned wrapper for anything that implements InternalRuntime, used to add a Runtime impl.
86pub struct OwnedRuntime<'a>(RuntimeWrapper<'a>, pub(crate) Box<dyn InternalRuntime + 'a>);
87
88impl<'a> Deref for OwnedRuntime<'a> {
89    type Target = RuntimeWrapper<'a>;
90
91    fn deref(&self) -> &Self::Target {
92        &self.0
93    }
94}
95
96impl<'a> Runtime<'a> for RuntimeWrapper<'a> {
97    fn push_boxed(&mut self, future: BoxFuture<'static, ()>) {
98        InternalRuntime::push_boxed(self.0, future);
99    }
100
101    fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a> {
102        SpawnedFuture(InternalRuntime::push_boxed(self.0, future), self.0)
103    }
104
105    fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()> {
106        InternalRuntime::sleep(self.0, duration)
107    }
108
109    fn stop(&mut self) -> Stop {
110        InternalRuntime::stop(self.0)
111    }
112}
113
114impl<'a, T: InternalRuntime + Sized> Runtime<'a> for T {
115    fn push_boxed(&mut self, future: BoxFuture<'static, ()>) {
116        InternalRuntime::push_boxed(self, future);
117    }
118
119    fn spawn_boxed(&'a mut self, future: BoxFuture<'static, ()>) -> SpawnedFuture<'a> {
120        SpawnedFuture(InternalRuntime::push_boxed(self, future), self)
121    }
122
123    fn sleep<'b>(&'a self, duration: Duration) -> BoxFuture<'b, ()> {
124        InternalRuntime::sleep(self, duration)
125    }
126
127    fn stop(&mut self) -> Stop {
128        InternalRuntime::stop(self)
129    }
130}
131
132/// Trait to construct a runtime
133pub trait StartableRuntime<'a>: InternalRuntime + Sized + 'a {
134    /// Constructs some new runtime
135    fn new() -> OwnedRuntime<'a> {
136        let mut bx = Box::new(Self::construct());
137        OwnedRuntime(
138            RuntimeWrapper(unsafe { (bx.as_mut() as *mut dyn InternalRuntime).as_mut().unwrap() }),
139            bx,
140        )
141    }
142
143    /// Internal function to make a new runtime. Only to be used by new() to create an
144    /// OwnedRuntime. Automatically implemented for T where T: Default
145    fn construct() -> Self;
146}
147
148impl<'a, T: InternalRuntime + Sized + 'a> StartableRuntime<'a> for T
149where
150    T: Default,
151{
152    fn construct() -> Self {
153        Self::default()
154    }
155}