Created
April 17, 2023 15:02
-
-
Save arifd/ec7b8962aa3a09298cc05bb55a89bb46 to your computer and use it in GitHub Desktop.
rust tokio select perculiarities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[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