Skip to content

Commit

Permalink
doc(select): add alternatives section
Browse files Browse the repository at this point in the history
  • Loading branch information
Ddystopia committed Jan 18, 2025
1 parent a82bdee commit 8626878
Showing 1 changed file with 94 additions and 0 deletions.
94 changes: 94 additions & 0 deletions tokio/src/macros/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,100 @@ macro_rules! doc {
/// application is shutting down, then you probably don't care that partially
/// read data is lost.
///
/// # Alternatives from the Ecosystem
///
/// The `select!` macro is a versatile tool for working with multiple asynchronous
/// branches, allowing tasks to run concurrently within the same thread. However,
/// depending on your use case, ecosystem alternatives can provide additional
/// benefits, such as more straightforward syntax, more transparent control flow or
/// reducing the burned of cancellation safety or fuse semantics.
///
/// ## Merging Streams
///
/// For cases where `loop { select! { ... } }` is used to poll multiple tasks,
/// stream merging offers a concise alternative, inherently handle cancellation-safe
/// processing, removing the risk of data loss. Libraries like
/// [`tokio-stream`](https://docs.rs/tokio-stream/latest/tokio_stream/) and
/// [`futures-concurrency`](https://docs.rs/futures-concurrency/latest/futures_concurrency/)
/// provide tools for merging streams and handling their outputs sequentially.
///
/// ### Example with `select!`
///
/// ```no_run
/// // open our IO types
/// let mut file = /* ... */;
/// let mut channel = /* ... */;
///
/// async fn read_send(file: ..., channel: ...) { /*...*/ }
///
/// // This loop re-creates the `read_send` future on each iteration. That means if
/// // `socket.read_packet` completes, `read_send` may have read data from the file,
/// // but not finished writing it to a channel, which can lead to data loss
/// loop {
/// select! {
/// _ = read_send(&mut file, &mut channel) => {}, // data loss can happen here
/// data = socket.read_packet() => {
/// // ...
/// }
/// }
/// }
/// ```
///
/// ### Moving to `merge`
///
/// By using merge, you can unify multiple asynchronous tasks into a single stream,
/// eliminating the need to manage tasks manually and reducing the risk of
/// unintended behavior like data loss.
///
/// ``no_run
/// let mut file = /* ... */;
/// let mut channel = /* ... */;
///
/// enum Message {
/// None,
/// Data(Vec<u8>),
/// }
///
/// async fn read_send(file: ..., channel: ...) { /*...*/ }
///
/// let a = futures_lite::stream::repeat_with(|| read_send(&mut file, &mut channel)).map(Message::None);
/// let b = futures_lite::stream::repeat_with(|| socket.read_packet()).map(Message::Data);
///
/// let mut s = a.merge(b);
/// while let Some(msg) = s.next().await {
/// match msg {
/// Message::None => continue,
/// Message::Data(data) => /*...*/ ,
/// }
/// }
/// ```
///
/// ## Racing Futures
///
/// If you need to wait for the first completion among several asynchronous tasks,
/// ecosystem utilities such as
/// [`futures-lite`](https://docs.rs/futures-lite/latest/futures_lite/) or
/// [`futures-concurrency`](https://docs.rs/futures-concurrency/latest/futures_concurrency/)
/// provide streamlined syntax for racing futures:
///
/// - [`futures-lite::future::or`](https://docs.rs/futures-lite/latest/futures_lite/future/fn.or.html)
/// - [`futures-lite::future::race`](https://docs.rs/futures-lite/latest/futures_lite/future/fn.race.html)
/// - [`futures_concurrency::future::Race`](https://docs.rs/futures-concurrency/latest/futures_concurrency/future/trait.Race.html)
///
/// ```no_run
/// let result = async {
/// futures_lite::future::race(
/// async { /* Task A */ },
/// async { /* Task B */ },
/// ).await
/// };
///
/// match result {
/// Ok(output) => println!("First task completed with: {output}"),
/// Err(err) => eprintln!("Error occurred: {err}"),
/// }
/// ```
///
/// # Examples
///
/// Basic select with two branches.
Expand Down

0 comments on commit 8626878

Please sign in to comment.