traffic_light/executor.rs
1//! The traffic-light Executor.
2//!
3//! # Examples
4//!
5//! ```
6//! use std::{error, result};
7//!
8//! use traffic_light::executor::Executor;
9//!
10//! fn main() -> result::Result<(), Box<dyn error::Error>> {
11//! Executor::block_on(async {
12//! // ...
13//! Ok::<(), Box<dyn error::Error>>(())
14//! })?;
15//!
16//! Ok(())
17//! }
18//! ```
19
20use std::{
21 pin::pin,
22 sync::Arc,
23 task::{Context, Poll, Waker},
24 thread,
25};
26
27use crate::thread::Thread;
28
29thread_local! {
30 static WAKER: Waker = Waker::from(Arc::new(Thread::default()));
31}
32
33/// The traffic-light Executor.
34pub struct Executor;
35
36impl Executor {
37 /// Blocks the current thread until the future is ready.
38 ///
39 /// # Panics
40 ///
41 /// Panics if the provided future panics.
42 ///
43 /// # Examples
44 ///
45 /// ```
46 /// # use std::{error,result};
47 /// #
48 /// use traffic_light::executor::Executor;
49 ///
50 /// # fn main() -> result::Result<(), Box<dyn error::Error>> {
51 /// let x: result::Result<(), Box<dyn error::Error>> =
52 /// Executor::block_on(async {
53 /// // ...
54 /// Ok(())
55 /// });
56 ///
57 /// assert!(x.is_ok());
58 /// #
59 /// # Ok(())
60 /// # }
61 /// ```
62 pub fn block_on<F: IntoFuture>(f: F) -> F::Output {
63 let mut f = pin!(f.into_future());
64
65 WAKER.with(|waker| {
66 let mut cx = Context::from_waker(waker);
67
68 loop {
69 match f.as_mut().poll(&mut cx) {
70 Poll::Ready(x) => return x,
71 Poll::Pending => thread::park(),
72 }
73 }
74 })
75 }
76}
77
78#[rustfmt::skip]
79#[cfg(test)]
80mod tests {
81 use std::{
82 error,
83 result,
84 };
85
86 use super::*;
87
88 #[test]
89 fn block_on_result_ok() {
90 let x: result::Result<(), Box<dyn error::Error>> =
91 Executor::block_on(async {
92 Ok(())
93 });
94
95 assert!(x.is_ok());
96 }
97
98 #[test]
99 fn block_on_result_err() {
100 let x: result::Result<(), &str> =
101 Executor::block_on(async {
102 Err("")
103 });
104
105 assert!(x.is_err());
106 }
107}