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