From 2c4549a18ae1595fec6a1737b4257daedd37a8fa Mon Sep 17 00:00:00 2001 From: Lev Eniseev <49126333+leniseev@users.noreply.github.com> Date: Tue, 9 Apr 2019 22:10:15 +0300 Subject: [PATCH] Add example of blocking environment (#1036) --- tokio/examples/README.md | 2 + tokio/examples/blocking.rs | 87 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 tokio/examples/blocking.rs diff --git a/tokio/examples/README.md b/tokio/examples/README.md index 02e5304b6..ac9e9b42f 100644 --- a/tokio/examples/README.md +++ b/tokio/examples/README.md @@ -55,6 +55,8 @@ A high level description of each example is: * [`manual-runtime`](manual-runtime.rs) - manually composing a runtime. +* [`blocking`](blocking.rs) - perform heavy computation in blocking environment. + If you've got an example you'd like to see here, please feel free to open an issue. Otherwise if you've got an example you'd like to add, please feel free to make a PR! diff --git a/tokio/examples/blocking.rs b/tokio/examples/blocking.rs new file mode 100644 index 000000000..e7d5da6c8 --- /dev/null +++ b/tokio/examples/blocking.rs @@ -0,0 +1,87 @@ +//! An example of using blocking funcion annotation. +//! +//! This example will create 8 "heavy computation" blocking futures and 8 +//! non-blocking futures with 4 threads core threads in runtime. +//! Each non-blocking future will print it's id and return immideatly. +//! Each blocking future will print it's id on start, sleep for 1000 ms, print +//! it's id and return. +//! +//! Note how non-blocking threads are executed before blocking threads finish +//! their task. + +extern crate tokio; +extern crate tokio_threadpool; + +use std::thread; +use std::time::Duration; +use tokio::prelude::*; +use tokio::runtime::Builder; +use tokio_threadpool::blocking; + +/// This future blocks it's poll method for 1000 ms. +struct BlockingFuture { + value: i32, +} + +impl Future for BlockingFuture { + type Item = (); + type Error = (); + + fn poll(&mut self) -> Poll { + println!("Blocking begin: {}!", self.value); + // Try replacing this part with commnted code + blocking(|| { + println!("Blocking part annotated: {}!", self.value); + thread::sleep(Duration::from_millis(1000)); + println!("Blocking done annotated: {}!", self.value); + }) + .map_err(|err| panic!("Error in blocing block: {:?}", err)) + // println!("Blocking part annotated: {}!", self.value); + // thread::sleep(Duration::from_millis(1000)); + // println!("Blocking done annotated: {}!", self.value); + // Ok(Async::Ready(())) + } +} + +/// This future returns immideatly. +struct NonBlockingFuture { + value: i32, +} + +impl Future for NonBlockingFuture { + type Item = (); + type Error = (); + + fn poll(&mut self) -> Poll { + println!("Non-blocking done: {}!", self.value); + Ok(Async::Ready(())) + } +} + +/// This future spawns child futures. +struct SpawningFuture; + +impl Future for SpawningFuture { + type Item = (); + type Error = (); + + fn poll(&mut self) -> Poll { + for i in 0..8 { + let blocking_future = BlockingFuture { value: i }; + + tokio::spawn(blocking_future); + } + for i in 0..8 { + let non_blocking_future = NonBlockingFuture { value: i }; + tokio::spawn(non_blocking_future); + } + Ok(Async::Ready(())) + } +} + +fn main() { + let spawning_future = SpawningFuture; + + let runtime = Builder::new().core_threads(4).build().unwrap(); + runtime.block_on_all(spawning_future).unwrap(); +}