Tokio aims to provide building blocks to write reliable and fast asynchronous programs in Rust. Recently announced Tokio 1.0 supports TCP, UDP, timers, a multi-threaded, work-stealing scheduler, and more.
This is a minimal example of how you would define a service waiting for an incoming request on a socket and spawning a thread to serve it:
use tokio::net::{TcpListener, TcpStream};
let mut listener = TcpListener::bind(&addr).await?;
loop {
let (mut socket, _) = listener.accept().await?;
tokio::spawn(async move {
// handle request
});
}
Tokio uses cooperative multitasking to run multiple green threads implemented as async
blocks. This implies that well-behaved tasks should yield control back to Tokio's scheduler to enable efficient task multiplexing and prevent starvation.
Tokio also provides support to share state across connections either by using tokio::sync::Mutex
or channels. Tokio mutexes can be safely used in an async
context, for example:
async fn increment_and_do_stuff(mutex: &tokio::sync::Mutex<i32>) {
let mut lock = mutex.lock().await;
*lock += 1;
do_something_async().await;
} // lock goes out of scope here
This approach, though, is only advisable for the simplest cases. Channels, on the contrary, are the preferred approach for most cases. They involve spawning a dedicated thread to manage the state and modify it using message passing. Tokio provides support for different channel types, including multi-producer, single-consumer; single-producer, single-channel; multi-producer, multi-consumer; and single-producer, multi-consumer.
Another functional area covered by Tokio is asynchronous I/O, with two fundamental traits, AsyncRead
and AsyncWrite
. AsyncRead
and AsyncWrite
enable reading from and writing to byte streams and are implemented by a number of specific classes, such as TcpStream, File
, and Stdout
.
As a final note on Tokio features, it is worth mentioning that Tokio also provides select
to concurrently execute asynchronous code, and a Stream
trait to iterate over async sequences.
Tokio 1.0 comes at the end of a period of relative instability at the API level, say its developers, mostly due to Rust getting support for async/await
. With 1.0, they are planning to keep Tokio stable for at least five years, with no plans to start working on Tokio 2.0 for at least three years.