A runtime for writing reliable network applications without compromising speed.
Tokio is an event-driven, non-blocking I/O platform for writing asynchronousapplications with the Rust programming language. At a high level, itprovides a few major components:
Guide level documentation is found on thewebsite.
Tokio consists of a number of modules that provide a range of functionalityessential for implementing asynchronous applications in Rust. In thissection, we will take a brief tour of Tokio, summarizing the major APIs andtheir uses.
The easiest way to get started is to enable all features. Do this byenabling thefull feature flag:
tokio = { version = "1", features = ["full"] }Tokio is great for writing applications and most users in this case shouldn’tworry too much about what features they should pick. If you’re unsure, we suggestgoing withfull to ensure that you don’t run into any road blocks while you’rebuilding your application.
This example shows the quickest way to get started with Tokio.
tokio = { version = "1", features = ["full"] }As a library author your goal should be to provide the lightest weight cratethat is based on Tokio. To achieve this you should ensure that you only enablethe features you need. This allows users to pick up your crate without havingto enable unnecessary features.
This example shows how you may want to import features for a library that justneeds totokio::spawn and use aTcpStream.
tokio = { version = "1", features = ["rt", "net"] }Asynchronous programs in Rust are based around lightweight, non-blockingunits of execution calledtasks. Thetokio::task module providesimportant tools for working with tasks:
spawn function andJoinHandle type, for scheduling a new taskon the Tokio runtime and awaiting the output of a spawned task, respectively,Thetokio::task module is present only when the “rt” feature flagis enabled.
Thetokio::sync module contains synchronization primitives to use whenneeding to communicate or share data. These include:
oneshot,mpsc, andwatch), for sending valuesbetween tasks,Mutex, for controlling access to a shared, mutablevalue,Barrier type, for multiple tasks to synchronize beforebeginning a computation.Thetokio::sync module is present only when the “sync” feature flag isenabled.
Thetokio::time module provides utilities for tracking time andscheduling work. This includes functions for settingtimeouts fortasks,sleeping work to run in the future, orrepeating an operation at aninterval.
In order to usetokio::time, the “time” feature flag must be enabled.
Finally, Tokio provides aruntime for executing asynchronous tasks. Mostapplications can use the#[tokio::main] macro to run their code on theTokio runtime. However, this macro provides only basic configuration options. Asan alternative, thetokio::runtime module provides more powerful APIs for configuringand managing runtimes. You should use that module if the#[tokio::main] macro doesn’tprovide the functionality you need.
Using the runtime requires the “rt” or “rt-multi-thread” feature flags, toenable the basicsingle-threaded scheduler and thethread-poolscheduler, respectively. See theruntime moduledocumentation for details. In addition, the “macros” featureflag enables the#[tokio::main] and#[tokio::test] attributes.
Tokio is able to concurrently run many tasks on a few threads by repeatedlyswapping the currently running task on each thread. However, this kind ofswapping can only happen at.await points, so code that spends a long timewithout reaching an.await will prevent other tasks from running. Tocombat this, Tokio provides two kinds of threads: Core threads and blockingthreads. The core threads are where all asynchronous code runs, and Tokiowill by default spawn one for each CPU core. The blocking threads arespawned on demand, can be used to run blocking code that would otherwiseblock other tasks from running and are kept alive when not used for a certainamount of time which can be configured withthread_keep_alive.Since it is not possible for Tokio to swap out blocking tasks, like itcan do with asynchronous code, the upper limit on the number of blockingthreads is very large. These limits can be configured on theBuilder.
To spawn a blocking task, you should use thespawn_blocking function.
#[tokio::main]asyncfnmain() {// This is running on a core thread.letblocking_task=tokio::task::spawn_blocking(|| {// This is running on a blocking thread.// Blocking here is ok. });// We can wait for the blocking task like this:// If the blocking task panics, the unwrap below will propagate the// panic.blocking_task.await.unwrap();}If your code is CPU-bound and you wish to limit the number of threads usedto run it, you should run it on another thread pool such asrayon. Youcan use anoneshot channel to send the result back to Tokio when therayon task finishes.
As well as scheduling and running tasks, Tokio provides everything you needto perform input and output asynchronously.
Thetokio::io module provides Tokio’s asynchronous core I/O primitives,theAsyncRead,AsyncWrite, andAsyncBufRead traits. In addition,when the “io-util” feature flag is enabled, it also provides combinators andfunctions for working with these traits, forming as an asynchronouscounterpart tostd::io.
Tokio also includes APIs for performing various kinds of I/O and interactingwith the operating system asynchronously. These include:
tokio::net, which contains non-blocking versions ofTCP,UDP, andUnix Domain Sockets (enabled by the “net” feature flag),tokio::fs, similar tostd::fs but for performing filesystem I/Oasynchronously (enabled by the “fs” feature flag),tokio::signal, for asynchronously handling Unix and Windows OS signals(enabled by the “signal” feature flag),tokio::process, for spawning and managing child processes (enabled bythe “process” feature flag).A simple TCP echo server:
usetokio::net::TcpListener;usetokio::io::{AsyncReadExt,AsyncWriteExt};#[tokio::main]asyncfnmain()->Result<(),Box<dynstd::error::Error>> {letlistener=TcpListener::bind("127.0.0.1:8080").await?;loop {let (mutsocket,_)=listener.accept().await?;tokio::spawn(asyncmove {letmutbuf= [0;1024];// In a loop, read data from the socket and write the data back.loop {letn=matchsocket.read(&mutbuf).await {// socket closedOk(n)ifn==0=>return,Ok(n)=>n,Err(e)=> {eprintln!("failed to read from socket; err = {:?}",e);return; } };// Write the data backifletErr(e)=socket.write_all(&buf[0..n]).await {eprintln!("failed to write to socket; err = {:?}",e);return; } } }); }}Tokio uses a set offeature flags to reduce the amount of compiled code. Itis possible to just enable certain features over others. By default, Tokiodoes not enable any features but allows one to enable a subset for their usecase. Below is a list of the available feature flags. You may also noticeabove each function, struct and trait there is listed one or more feature flagsthat are required for that item to be used. If you are new to Tokio it isrecommended that you use thefull feature flag which will enable all public APIs.Beware though that this will pull in many extra dependencies that you may notneed.
full: Enables all Tokio public API features listed below excepttest-util.rt: Enablestokio::spawn, the basic (current thread) scheduler,and non-scheduler utilities.rt-multi-thread: Enables the heavier, multi-threaded, work-stealing scheduler.io-util: Enables the IO basedExt traits.io-std: EnableStdout,Stdin andStderr types.net: Enablestokio::net types such asTcpStream,UnixStream andUdpSocket,as well as (on Unix-like systems)AsyncFdtime: Enablestokio::time types and allows the schedulers to enablethe built in timer.process: Enablestokio::process types.macros: Enables#[tokio::main] and#[tokio::test] macros.sync: Enables alltokio::sync types.signal: Enables alltokio::signal types.fs: Enablestokio::fs types.test-util: Enables testing based infrastructure for the Tokio runtime.Note:AsyncRead andAsyncWrite traits do not require any features and arealways available.
These features do not expose any new API, but influence internalimplementation aspects of Tokio, and can pull in additionaldependencies.
parking_lot: As a potential optimization, use theparking_lot crate’ssynchronization primitives internally. MSRV may increase according to theparking_lot release in use.These feature flags enableunstable features. The public API may break in 1.xreleases. To enable these features, the--cfg tokio_unstable must be passed torustc when compiling. This is easiest done using theRUSTFLAGS env variable:RUSTFLAGS="--cfg tokio_unstable".
tracing: Enables tracing events.Types which are documented locally in the Tokio crate, but does not actuallylive here.
fsAsynchronous file and standard stream adaptation.
Traits, helpers, and type definitions for asynchronous I/O functionality.
TCP/UDP/Unix bindings fortokio.
processAn implementation of asynchronous process management for Tokio.
rtThe Tokio runtime.
signalAsynchronous signal handling for Tokio
Due to theStream trait’s inclusion instd landing later than Tokio’s 1.0release, most of the Tokio stream utilities have been moved into thetokio-streamcrate.
syncSynchronization primitives for use in asynchronous contexts.
Asynchronous green-threads.
timeUtilities for tracking time.
macrosWait on multiple concurrent branches, returning whenall branchescomplete.
Pins a value on the stack.
macrosWait on multiple concurrent branches, returning when thefirst branchcompletes, cancelling the remaining branches.
Declares a new task-local key of typetokio::task::LocalKey.
macrosWait on multiple concurrent branches, returning whenall branchescomplete withOk(_) or on the firstErr(_).
rtSpawns a new asynchronous task, returning aJoinHandle for it.