async-std 0.99.12: async/.await is ready!

Today marks the release of Rust 1.39, with a finally ready async/.await feature.

In our announcement blog post, we communicated our intent to ship async-std on the release day of this feature. We will miss this deadline by a few days, but give you a short roadmap here.

The delay is caused by the futures-rs library, which we depend on, making their final release yesterday. We highly respect futures-rs timeline, the time was well spent in release polish and we congratulate the team to their release! Still, this means that we will release async-std a little later, to also give ourselves time for quality control and release polish. The current release date is Monday, November 11th.

Today, we will release async-std 0.99.12, a final point release for you to play around with the new async/.await feature.

The best way to try futures-rs

async-std is an easy to use, well-documented library that provides an interface very close to Rust’s standard library. It provides implementations of all important I/O types like TcpListener, File and others. It is compatible with all libraries that are using futures-rs as their library interface.

In practice, that means that async_std::stream::Stream can be used anywhere a futures::stream::Stream is expected and all I/O types can be used anywhere AsyncRead and AsyncWrite are expected.

async-std provides a book to learn the finer details and background, which we will keep continuously expanding. It supplements the official async book.

On top of that, async-std makes spawning tasks as easy as possible. For example, async-std unifies blocking and non-blocking tasks in the async_std::task module under an interface similar to std::thread::JoinHandle.

use async_std::task;
use std::thread;
use std::time::Duration;

fn main() {
    task::block_on(async {
        let mut tasks: Vec<task::JoinHandle<()>> = vec![];
        let task = task::spawn(async {
        let blocking = task::spawn_blocking(|| {
        for task in tasks {

Note: This examples still needs the unstable feature of the library.

The JoinHandle makes it easy to spawn tasks and retrieve their results in a uniform fashion. Also, every spawned task is stored within a single allocation, making this process quick and efficient.

See the task module for more details.

Current Status

async-std has been mainly focused on stabilising and trying out its interface over the last couple of months. We have used the time to gather confidence in our concept of the port of Rust’s std to the async world.

A lot of time has been spent in proper integration into the current futures library, so that you can use both the direct async-std interface and the futures-rs common traits to interact with async-std.

We have moved a number of newer features under the feature flag unstable, which acts as a stability gate similar to the #![feature(…)] attribute used in nightly versions of Rust’s standard library. One of those features is a very fast implementation of MPMC (Multiple Sender Multiple Receiver) channels, which will cover most usecases people might have. We’re still taking feedback on their interface.

We feel confident about the release and the stability promises it brings. The 1.0 version covers all important parts to build an async system.

Meet us at RustFest!

Finally, meet us all at the async/.await special edition of RustFest! We’ll be around the whole weekend, including the impl Days! We’re happy to assist you in making your library run on top of async-std or help you on your first contribution to async-std or related libraries.

Announcing async-std

We are excited to announce a beta release of async-std with the intent to publish version 1.0 by September 26th, 2019.

async-std is a library that looks and feels like the Rust standard library, except everything in it is made to work with async/await exactly as you would expect it to.

The library comes with a book and polished API documentation, and will soon provide a stable interface to base your async libraries and applications on. While we don't promise API stability before our 1.0 release, we also don't expect to make any breaking changes.


Consider the following code using blocking filesystem APIs to read from a file:

use std::fs::File;
use std::io::{self, Read};

fn read_file(path: &str) -> io::Result<String> {
    let mut file = File::open(path)?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer)?;

To make read_file asynchronous, it would be great if we could just sprinkle the code with async/await keywords where appropriate. That kind of experience is exactly what async-std offers:

use async_std::fs::File;
use async_std::io::{self, Read};

async fn read_file(path: &str) -> io::Result<String> {
    let mut file = File::open(path).await?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer).await?;

Another interesting highlight is the task module, providing an interface that feels similar to the thread module from the standard library. Running a concurrent task using async-std is as easy as spawning a thread:

use async_std::task;
use std::time::Duration;

fn main() {
    let task = task::spawn(async {

    task::block_on(async {
        println!("waiting for the task");
        let res = task.await;
        println!("task ended with result {:?}", res);

When run, this program prints the following:

waiting for the task
task ended with result "hello"

Spawned tasks can be awaited the same way spawned threads can be joined. It is also possible to declare task-local variables that work exactly like thread-local variables. You can really think of tasks as lightweight threads and treat them that way!

If you'd like a longer tour around the library, head over to our chat tutorial.

A fresh start for async/await

async-std is designed to support the new async programming model (to be stabilized in Rust 1.39), along with a set of coding practices derived from our previous experience in the field. To that end, async-std not only provides you with async versions of the I/O functionality found in std, but also with async versions of concurrency primitives like Mutex and RwLock.

async-std comes with a fresh codebase and carefully thought out semantics. It is a faithful port of Rust's standard library, sticking to its tried-and-true interface, with only minimal differences where absolutely necessary.

By mimicking standard library's well-understood APIs as closely as possible, we hope users will have an easy time learning how to use async-std and switching from thread-based blocking APIs to asynchronous ones. If you're familiar with Rust's standard library, very little should come as a surprise.

Relationship to futures and other libraries

async-std is a standalone library based on the Future trait and supporting set of traits from the futures library.

Since parts of the futures API is still in active development and we want to provide strong stability guarantees to our users, we're relying on a minimal and most stable set of traits from futures.

At the same time, we're serious about compatibility with the whole async ecosystem and therefore have put effort into designing the API in such a way that does not put our crate above other similar ones, or lock users into our ecosystem. We do not require compatibility layers or any extra setup to use async-std with other libraries like futures.

Efficient single-allocation tasks

One of the promises of zero-cost futures in Rust has always been that every spawned task incurs the cost of a single allocation only. However, that has always been a white lie... or at least until today.

Most executors typically perform two allocations per spawn, one for the task state and one for the future. Additionally, in order to await the result of a task, a oneshot channel is typically used, which creates a third allocation.

In order to reduce the amount of allocation, we've implemented a library called async-task that performs a single allocation per spawned task, and is able to await the result of the task without creating an extra channel. That gets us from three allocations per spawn to just a single allocation!

We will follow up with more blog posts on interesting performance tidbits.

Teaching, documentation, and help

async-std comes with a fully documented API and a book, teaching you about both using the library and writing libraries or applications in it.

We treat documentation as a first-class feature, so if you find anything in it confusing, please file an issue or ask questions in our Discord channel. Documentation is at the core of our promise and we're always eager to improve it!

The path towards 1.0

async-std is currently in beta. We're aiming for a stable release by September 26th, 2019, on the same day beta release of Rust 1.39 comes out.

The initial version number 0.99 expresses how close we are to 1.0. async-std will remain in beta until async/await is on a committed track to stabilization.

During our beta period, we will release a new patch version for API extensions and backwards-compatible changes, and a new minor version for breaking changes. In the ideal scenario, we will manage without any breaking changes towards 1.0.

Security and reliability

async-std has documented SemVer and security practices.

We use a small number of well-vetted and checked dependencies, implementing all the core primitives async-std needs.

Community involvement

async-std was developed by Stjepan Glavina in collaboration with Yoshua Wuyts and reuses many ideas from crossbeam that have been successful in the area of concurrency throughout the Rust ecosystem.

It is designed and implemented with feedback from the industry and open source community. Now that the library is finally published, we'd like to welcome broader community of contributors. Over the next few weeks, we need work with testing, filling in remaining gaps in the API, and writing more documentation. Examples and experience reports are also very welcome!

See our contribution section for details. Want to help out? Feel free to grab one of the good first issues.

Thanks and sponsoring

Thanks to all contributors and early users for providing us feedback during development!

Finally, thanks to Ferrous Systems for funding this project! If you'd like to help fund development on async-std, please get in contact with us.

  • 2 of 2