Serving HTTP requests
Querying a database
A game render and input loop
Event loops in embedded systems
“Crack then fry the eggs. Meanwhile, fry the bacon for five minutes, or until crispy.”
fn breakfast() {
cook_eggs();
fry_bacon();
}
fn cook_eggs() {
crack_eggs();
fry_eggs();
}
fn crack_eggs() {
println!("Started cracking egg.");
random_sleep();
println!("Finished cracking egg.");
}
fn random_sleep() { ... }
fn fry_eggs() { ... } // Prints and sleeps
fn fry_bacon() { ... } // Prints and sleeps
Started cracking egg.
Finished cracking egg.
Started frying egg.
Finished frying egg.
Started frying bacon.
Finished frying bacon.
async fn breakfast() {
cook_eggs().await;
fry_bacon().await;
}
async fn cook_eggs() {
crack_eggs().await;
fry_eggs().await;
}
async fn crack_eggs() {
println!("Started cracking egg.");
random_sleep().await;
println!("Finished cracking egg.");
}
async fn fry_eggs() { ... }
async fn fry_bacon() { ... }
async fn random_sleep() { ... }
Started cracking egg.
Finished cracking egg.
Started frying egg.
Finished frying egg.
Started frying bacon.
Finished frying bacon.
“Meanwhile, fry the bacon.”
async fn breakfast() {
join!(cook_eggs(), fry_bacon());
}
Started frying bacon.
Started cracking egg.
Finished cracking egg.
Started frying egg.
Finished frying bacon.
Finished frying egg.
“Fry bacon for five minutes, or until crispy.”
async fn fry_bacon() {
println!("Started frying bacon.");
// This is simplified
select! {
() = timer() => (),
() = crisp_bacon() => ()
};
println!("Finished frying bacon.");
}
async fn timer() { ... }
async fn crisp_bacon() { ... }
Started frying bacon.
Started timer.
Started crisping bacon.
Finished timer.
Finished frying bacon.
“Cook the eggs using a spoon: use a spoon to crack them and then fry them. Meanwhile, use a spoon to fry the bacon.”
async fn breakfast() {
let mut spoon = find_spoon();
join!(cook_eggs(&mut spoon), fry_bacon(&mut spoon))
}
async fn cook_eggs(spoon: &mut Spoon) { ... }
async fn fry_bacon(spoon: &mut Spoon) { ... }
type SpoonMutex = Arc<Mutex<Spoon>>;
async fn cook_eggs(spoon_mutex: SpoonMutex) {
let spoon = spoon_mutex.lock().await;
...
drop(spoon);
}
async fn fry_bacon(spoon_mutex: SpoonMutex) { ... }
async fn breakfast() {
let spoon_mutex = find_spoon();
join!(cook_eggs(spoon_mutex.clone()),
fry_bacon(spoon_mutex))
}
Started cracking egg.
Finished cracking egg.
Started frying egg.
Finished frying egg.
Started frying bacon.
Finished frying bacon.
“Cook the eggs using a spoon: use a spoon to crack them and then fry them using a pan. Meanwhile, use a spoon and use a pan to fry the bacon.”
async fn cook_eggs(spoon_mutex: SpoonMutex,
pan_mutex: PanMutex) {
let spoon = spoon_mutex.lock().await;
crack_eggs().await;
let pan = pan_mutex.lock().await;
fry_eggs().await;
drop(spoon);
drop(pan);
}
async fn fry_bacon(spoon_mutex: SpoonMutex,
pan_mutex: PanMutex) {
join!(spoon_mutex.lock(), pan_mutex.lock());
...
drop(spoon);
drop(pan);
}
Started cracking egg.
Finished cracking egg.
let (spoon, pan) = loop {
let maybe_spoon = try_lock_spoon(&spoon_mutex).await;
let maybe_pan = try_lock_pan(&pan_mutex).await;
match (maybe_spoon, maybe_pan) {
(Some(spoon), None) => drop(spoon),
(None, Some(pan)) => drop(pan),
(Some(spoon), Some(pan)) => break (spoon, pan),
(None, None) => (),
}
};
async fn fry_eggs(...) {
let (spoon, pan) = loop {...}
...
}
async fn fry_bacon(...) {
let (spoon, pan) = loop {...}
...
}
Started cracking egg.
Finished cracking egg.
type SpoonAndPanMutex = Arc<Mutex<(Spoon, Pan)>>;
async fn cook_eggs(mutex: SpoonAndPanMutex) {
let spoon_and_pan = mutex.lock().await;
...
drop(spoon_and_pan);
}
async fn fry_bacon(mutex: SpoonAndPanMutex) {
let spoon_and_pan = mutex.lock().await;
...
drop(spoon_and_pan);
}
let (sender, receiver) = channel::<Message>(42);
async fn chef_actor(mut receiver: Receiver<Message>) {
let mut spoon = Spoon; // internal mutable state
let mut pan = Pan;
while let Some(msg) = receiver.next().await {
...
}
}
match msg {
// use the state
CrackEggs => crack_eggs(&mut spoon).await,
FryEggs => fry_eggs(&mut spoon, &mut pan).await,
FryBacon => fry_bacon(&mut spoon, &mut pan).await,
}
async fn crack_eggs(spoon: &mut Spoon) { .. }
async fn fry_eggs(spoon: &mut Spoon, pan: &mut Pan) { ... }
async fn fry_bacon(spoon: &mut Spoon, pan: &mut Pan) { ... }
async fn send_cook_eggs(mut sender: Sender<Message>) {
sender.send(CrackEggs).await;
sender.send(FryEggs).await;
}
async fn send_fry_bacon(mut sender: Sender<Message>) {
sender.send(FryBacon).await;
}
async fn breakfast() {
let (sender, receiver) = channel::<Message>(42);
join!(
chef_actor(receiver),
send_cook_eggs(sender.clone()),
send_fry_bacon(sender),
);
}
“He fixes radios by thinking!”
— Surely You're Joking, Mr. Feynman!