Using an executor

The second approach is to execute all tasks with an Executor  instance. This allows you to run multiple tasks in a single thread, even if some tasks can't be completed immediately. To use an Executor, you have to create and run it, but it will block the current thread and you should add all the necessary tasks to be executed at the start.

For example, if you want to open a socket and process the stream of every incoming connection, you have to create a main Future that will read the Stream of incoming connections and spawn a handler for processing the Stream of the data of the connection using the tokio::spawn method. After you have created it, you have to spawn the whole processing future with the executor. Take a look at the following example:

fn send_spawn() {
let (tx_sink, rx_stream) = mpsc::channel::<u8>(8);
let receiver = rx_stream.fold(0, |acc, value| {
println!("Received: {}", value);
future::ok(acc + value)
}).map(drop);
let spawner = stream::iter_ok::<_, ()>(1u8..11u8).map(move |x| {
let fut = tx_sink.clone().send(x).map(drop).map_err(drop);
tokio::spawn(fut);
}).collect();
let execute_all = future::join_all(vec![
to_box(spawner),
to_box(receiver),
]).map(drop);
tokio::run(execute_all);
}

In this example, we have created a channel. We have also created a stream from a sequence of integers using the stream::iter_ok method. We send all items of the stream to the channel, which reads all the incoming values and prints them to a console. We have already dealt with a similar example. In the current version, we use the tokio::spawn function to spawn a task in an executor of the current thread.

As you can see, to use the futures crate, you have to build chains of handlers. The resultant code is hard to maintain and improve. To simplify asynchronous code, the Rust compiler has started to support the async/await syntax.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.74.66