#futures #resolve #callback #watch #mvar

no-std async_cell

A Cell<Option> that you can await on

2 unstable releases

0.2.0 Sep 16, 2021
0.1.0 Apr 3, 2021

#146 in Asynchronous

Download history 610/week @ 2021-09-28 955/week @ 2021-10-05 1108/week @ 2021-10-12 917/week @ 2021-10-19 908/week @ 2021-10-26 583/week @ 2021-11-02 485/week @ 2021-11-09 551/week @ 2021-11-16 555/week @ 2021-11-23 766/week @ 2021-11-30 860/week @ 2021-12-07 706/week @ 2021-12-14 483/week @ 2021-12-21 489/week @ 2021-12-28 683/week @ 2022-01-04 828/week @ 2022-01-11

2,653 downloads per month

MIT license

496 lines


Build Status Latest Version Documentation

The key type of this crate is AsyncCell which can be found in both thread-safe and single-threaded variants. It is intended as a useful async primitive which can replace more expensive channels in a fair number of cases.

AsyncCell<T> behaves a lot like a Cell<Option<T>> that you can await on.

This is used to create futures from a callbacks:

use async_cell::sync::AsyncCell;

let cell = AsyncCell::shared();
let future = cell.take_shared();

thread::spawn(move || cell.set("Hello, World!"));

println!("{}", future.await);

You can also use an async_cell for static variable initilization, wherever the blocking behavior of a OnceCell is unacceptable:

use async_cell::sync::AsyncCell;

// AsyncCell::new() is const!
static GREETING: AsyncCell<String> = AsyncCell::new();

// Read the file on a background thread.
thread::spawn(|| {
    let hello = std::fs::read_to_string("tests/hello.txt").unwrap();

// Do some work while waiting for the file.

// And greet the user!
println!("{}", &GREETING.get().await);

Async cells can also be used to react to the latest value of a variable, since the same cell can be reused as many times as desired. This is one way AsyncCell differs from a one-shot channel:

use async_cell::sync::AsyncCell;

// Allocate space for our timer.
let timer = AsyncCell::<i32>::shared();

// Try to print out the time as fast as it updates.
let watcher = timer.take_weak();
spawn(async move {
    while let Some(time) = (&watcher).await {
        println!("Launch in T-{} seconds!", time);

// Begin counting down!
for i in (0..60).rev() {

Although this crate contains a number of utility functions, you can often make due with just AsyncCell::new, AsyncCell::set, and AsyncCell::take.


Do not use AsyncCell in situations with high contention! As a rule of thumb, try to fill cells from one thread or task and empty from one other. Although multiple futures can wait on the same cell, that case is not highly optimized.

Also do not confuse an AsyncCell with full-blown channel. Channels deliver all written value to readers; readers of an cell will only see the most recently written value.


~25K SLoC