Crate async_cell[−][src]
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 aCell<Option<T>>that you can await on.
For example, it can be used to author futures in a callbacky style:
use async_cell::sync::AsyncCell; let cell = AsyncCell::shared(); let future = cell.take_shared(); std::thread::spawn(move || cell.set("Hello, World!")); println!("{}", future.await);
In place of something like tokio::sync::watch to react to the latest value
of a variable:
use async_cell::sync::AsyncCell; // Allocate space for our counter. let counter_to_print = AsyncCell::shared(); // Try to print out the counts as fast as we receive them. let c = counter_to_print.clone(); spawn(async move { while let Some(count) = c.take().await { println!("Latest count: {}", count); } }); // Begin counting! for i in 0..1000 { counter_to_print.set(Some(i)); } counter_to_print.set(None);
To juggle a Waker within more complex data structures:
use async_cell::unsync::AsyncCell; use std::cell::RefCell; // A simple channel for sending numbers. struct MpscStack { ready: AsyncCell, list: RefCell<Vec<i32>>, } impl MpscStack { // Push a number to the end of the channel. fn push(&self, x: i32) { let mut list = self.list.borrow_mut(); if list.is_empty() { self.ready.notify(); } list.push(x); } // Pop a number off the end of the channel, blocking while it is empty. async fn pop(&self) -> i32 { loop { if let Some(x) = self.list.borrow_mut().pop() { return x; } self.ready.take().await; } } }
Or can be used in place of a lazy_static + a oneshot channel to initialize some resource:
use async_cell::sync::AsyncCell; // AsyncCell::new() is const! static DATA: AsyncCell<String> = AsyncCell::new(); // Read the file on a background thread. std::thread::spawn(|| { let hello = std::fs::read_to_string("tests/hello.txt").unwrap(); DATA.set(hello); }); // Do some work while waiting for the file. // And ready! assert_eq!(&DATA.take().await, "Hello, World!\n");
What can’t async_cell do?
- Be used to broadcast data. If you need multiple concurrent consumers, get yourself a channel.
- Guarantee that multiple sent values are received. When a cell is set in a loop, the receiver might wake up only once, long after, and take the last.
Although this crate contains a number of utility functions, you should
generally be able to make due with just
AsyncCell::new,
AsyncCell::set, and
AsyncCell::take.
Modules
| sync | Types which can be shared across threads. |
| unsync | Types for single-threaded and no_std use. |