Skip to content

Instantly share code, notes, and snippets.

@arifd
Created April 17, 2023 15:02
Show Gist options
  • Save arifd/ec7b8962aa3a09298cc05bb55a89bb46 to your computer and use it in GitHub Desktop.
Save arifd/ec7b8962aa3a09298cc05bb55a89bb46 to your computer and use it in GitHub Desktop.
rust tokio select perculiarities
#[cfg(test)]
mod tests {
use std::{
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
time::Duration,
};
const INTERVAL: Duration = Duration::from_millis(500);
#[tokio::test]
async fn select_wont_cancel_a_spawned_task_must_call_abort_manually() {
let counter = Arc::new(AtomicUsize::new(0));
let _counter = counter.clone();
let mut count_when_terminated = 0;
// spawn a never ending task
let mut infinite = tokio::spawn(async move {
loop {
tokio::time::sleep(INTERVAL).await;
_counter.fetch_add(1, Ordering::Relaxed);
}
});
// spawn a terminating task
let terminates = tokio::spawn(async move {
tokio::time::sleep(INTERVAL * 3).await;
});
// assume that select will cancel `infinite`
// when `terminates` concludes
tokio::select! {
_ = terminates => {
count_when_terminated = counter.load(Ordering::Relaxed);
infinite.abort(); // <-- this is necessary because of `spawn`!
}
_ = &mut infinite => {}
};
// check that after waiting enough time for the counter to increase
// that it did not increase
tokio::time::sleep(INTERVAL * 2).await;
assert_eq!(counter.load(Ordering::Relaxed), count_when_terminated);
}
#[tokio::test]
async fn select_will_cancel_a_future_if_the_future_is_not_spawned() {
let counter = Arc::new(AtomicUsize::new(0));
let _counter = counter.clone();
let mut count_when_terminated = 0;
// spawn a never ending task
let infinite = async move {
loop {
tokio::time::sleep(INTERVAL).await;
_counter.fetch_add(1, Ordering::Relaxed);
}
};
// spawn a terminating task
let terminates = async move {
tokio::time::sleep(INTERVAL * 3).await;
};
// assume that select will cancel `infinite`
// when `terminates` concludes
tokio::select! {
_ = terminates => {
count_when_terminated = counter.load(Ordering::Relaxed);
}
_ = infinite => {}
};
// check that after waiting enough time for the counter to increase
// that it did not increase
tokio::time::sleep(INTERVAL * 2).await;
assert_eq!(counter.load(Ordering::Relaxed), count_when_terminated);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment