From e4470d30b08d0b431d79fe486def893483af91fa Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Sun, 13 Jun 2021 22:17:53 -0700 Subject: [PATCH] block-on: Add example from Chapter 20, Asynchronous Programming. --- block-on/.gitignore | 2 ++ block-on/Cargo.toml | 15 +++++++++++++++ block-on/src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 block-on/.gitignore create mode 100644 block-on/Cargo.toml create mode 100644 block-on/src/lib.rs diff --git a/block-on/.gitignore b/block-on/.gitignore new file mode 100644 index 0000000..ca98cd9 --- /dev/null +++ b/block-on/.gitignore @@ -0,0 +1,2 @@ +/target/ +Cargo.lock diff --git a/block-on/Cargo.toml b/block-on/Cargo.toml new file mode 100644 index 0000000..1ecdd80 --- /dev/null +++ b/block-on/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "block-on" +version = "0.1.0" +authors = ["You "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +waker-fn = "1.1" +futures-lite = "1.11" +crossbeam = "0.8" + +[dev-dependencies] +async-std = "1.7" diff --git a/block-on/src/lib.rs b/block-on/src/lib.rs new file mode 100644 index 0000000..da53b40 --- /dev/null +++ b/block-on/src/lib.rs @@ -0,0 +1,44 @@ +use waker_fn::waker_fn; // Cargo.toml: waker-fn = "1.1" +use futures_lite::pin; // Cargo.toml: futures-lite = "1.11" +use crossbeam::sync::Parker; // Cargo.toml: crossbeam = "0.8" +use std::future::Future; +use std::task::{Context, Poll}; + +pub fn block_on(future: F) -> F::Output { + let parker = Parker::new(); + let unparker = parker.unparker().clone(); + let waker = waker_fn(move || unparker.unpark()); + let mut context = Context::from_waker(&waker); + + pin!(future); + + loop { + match future.as_mut().poll(&mut context) { + Poll::Ready(value) => return value, + Poll::Pending => parker.park(), + } + } +} + +#[test] +fn test() { + assert_eq!(block_on(std::future::ready(42)), 42); + + use async_std::task::{spawn, sleep}; + use futures_lite::FutureExt; + use std::time::Duration; + + assert_eq!( + block_on({ + let one_sec = async { + sleep(Duration::from_secs(1)).await; + 43 + }; + let half_sec = async { + sleep(Duration::from_millis(500)).await; + 44 + }; + spawn(one_sec.race(half_sec)) + }), + 44); +}