rust / expert
Snippet
Driving Concurrent Futures with a Custom Select Multiplexer
This snippet demonstrates how to manually implement the Future trait to create a custom select combinator that polls two futures concurrently and returns the output of the first one to resolve. It uses generic constraints and Pin projection to safely poll the underlying futures in a non-blocking manner.
snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
use std::future::Future;use std::pin::Pin;use std::task::{Context, Poll};pub struct Select<A, B> {fut_a: A,fut_b: B,}impl<A, B, T> Future for Select<A, B>whereA: Future<Output = T> + Unpin,B: Future<Output = T> + Unpin,{type Output = T;fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {if let Poll::Ready(val) = Pin::new(&mut self.fut_a).poll(cx) {return Poll::Ready(val);}if let Poll::Ready(val) = Pin::new(&mut self.fut_b).poll(cx) {return Poll::Ready(val);}Poll::Pending}}pub fn select<A, B, T>(fut_a: A, fut_b: B) -> Select<A, B>whereA: Future<Output = T> + Unpin,B: Future<Output = T> + Unpin,{Select { fut_a, fut_b }}
Breakdown
1
pub struct Select<A, B>
Defines a generic struct wrapping two distinct future types to poll concurrently.
2
impl<A, B, T> Future for Select<A, B>
Implements the Future trait for the select wrapper, enforcing that both futures produce the same output type.
3
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>
The core driving method that checks both futures using a pinned reference.
4
if let Poll::Ready(val) = Pin::new(&mut self.fut_a).poll(cx)
Polls the first future; if it completes, returns the value immediately.