Skip to main content

hiver_runtime/
select.rs

1//! Select macro for waiting on multiple async operations
2//! 用于等待多个异步操作的select宏
3//!
4//! # Overview / 概述
5//!
6//! This module provides a foundation for the `select!` macro which allows
7//! waiting on multiple async operations and proceeding with the first one
8//! that completes.
9//!
10//! 本模块为 `select!` 宏提供基础,允许等待多个异步操作并处理第一个完成的。
11//!
12//! # Example / 示例
13//!
14//! ```rust,no_run,ignore
15//! use hiver_runtime::select;
16//! use hiver_runtime::time::{sleep, Duration};
17//!
18//! async fn example() {
19//!     let sleep1 = sleep(Duration::from_millis(100));
20//!     let sleep2 = sleep(Duration::from_millis(200));
21//!
22//!     select! {
23//!         _ = sleep1 => println!("First completed"),
24//!         _ = sleep2 => println!("Second completed"),
25//!     }
26//! }
27//! ```
28
29use std::future::Future;
30use std::pin::Pin;
31use std::task::{Context, Poll};
32
33/// Select from two futures, returning the first that completes
34/// 从两个future中选择,返回第一个完成的
35///
36/// # Example / 示例
37///
38/// ```rust,no_run,ignore
39/// use hiver_runtime::select::{select_two, SelectTwo};
40/// use hiver_runtime::time::{sleep, Duration};
41///
42/// async fn example() {
43///     let sleep1 = sleep(Duration::from_millis(100));
44///     let sleep2 = sleep(Duration::from_millis(200));
45///
46///     match select_two(sleep1, sleep2).await {
47///         SelectTwo::First(_) => println!("First completed"),
48///         SelectTwo::Second(_) => println!("Second completed"),
49///     }
50/// }
51/// ```
52pub fn select_two<F1, F2, T1, T2>(future1: F1, future2: F2) -> SelectTwo<F1, F2>
53where
54    F1: Future<Output = T1> + Unpin,
55    F2: Future<Output = T2> + Unpin,
56{
57    SelectTwo {
58        future1: Some(future1),
59        future2: Some(future2),
60    }
61}
62
63/// Select future for two futures
64/// 两个future的select future
65pub struct SelectTwo<F1, F2> {
66    future1: Option<F1>,
67    future2: Option<F2>,
68}
69
70impl<F1, F2, T1, T2> Future for SelectTwo<F1, F2>
71where
72    F1: Future<Output = T1> + Unpin,
73    F2: Future<Output = T2> + Unpin,
74{
75    type Output = SelectTwoOutput<T1, T2>;
76
77    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
78        // Try polling the first future
79        // 尝试轮询第一个future
80        if let Some(future1) = &mut self.future1 {
81            match Pin::new(future1).poll(cx) {
82                Poll::Ready(value) => {
83                    self.future1 = None;
84                    return Poll::Ready(SelectTwoOutput::First(value));
85                },
86                Poll::Pending => {},
87            }
88        }
89
90        // Try polling the second future
91        // 尝试轮询第二个future
92        if let Some(future2) = &mut self.future2 {
93            match Pin::new(future2).poll(cx) {
94                Poll::Ready(value) => {
95                    self.future2 = None;
96                    return Poll::Ready(SelectTwoOutput::Second(value));
97                },
98                Poll::Pending => {},
99            }
100        }
101
102        Poll::Pending
103    }
104}
105
106/// Output of selecting between two futures
107/// 两个future之间选择的输出
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub enum SelectTwoOutput<T1, T2> {
110    /// The first future completed
111    /// 第一个future完成了
112    First(T1),
113    /// The second future completed
114    /// 第二个future完成了
115    Second(T2),
116}
117
118/// Select from multiple futures
119/// 从多个future中选择
120///
121/// For Phase 2, this provides a simpler alternative to the full select! macro.
122/// 对于第2阶段,这提供了完整的select!宏的更简单替代方案。
123pub fn select_multiple<F>(futures: Vec<F>) -> SelectMultiple<F>
124where
125    F: Future + Unpin,
126{
127    SelectMultiple { futures }
128}
129
130/// Select future for multiple futures
131/// 多个future的select future
132pub struct SelectMultiple<F> {
133    futures: Vec<F>,
134}
135
136impl<F> Future for SelectMultiple<F>
137where
138    F: Future + Unpin,
139{
140    type Output = SelectMultipleOutput<F::Output>;
141
142    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
143        // Try polling each future
144        // 尝试轮询每个future
145        for (index, future) in self.futures.iter_mut().enumerate() {
146            match Pin::new(future).poll(cx) {
147                Poll::Ready(value) => {
148                    return Poll::Ready(SelectMultipleOutput::Completed(index, value));
149                },
150                Poll::Pending => {},
151            }
152        }
153
154        Poll::Pending
155    }
156}
157
158/// Output of selecting from multiple futures
159/// 从多个future中选择的输出
160#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub enum SelectMultipleOutput<T> {
162    /// A future completed with its index and value
163    /// 一个future完成了,带有其索引和值
164    Completed(usize, T),
165}
166
167/// Internal helper for select macro binding
168/// select宏绑定的内部辅助
169pub struct SelectMultipleBinding<T> {
170    /// Index of the completed future
171    /// 完成的future的索引
172    pub index: usize,
173
174    /// Output value from the future
175    /// 来自future的输出值
176    pub output: Option<T>,
177}
178
179#[cfg(test)]
180mod tests {
181    use super::*;
182    use std::task::{Context, Waker};
183
184    #[test]
185    fn test_select_two_output_first() {
186        let output: SelectTwoOutput<i32, i32> = SelectTwoOutput::First(42);
187        assert!(matches!(output, SelectTwoOutput::First(42)));
188    }
189
190    #[test]
191    fn test_select_two_output_second() {
192        let output: SelectTwoOutput<i32, i32> = SelectTwoOutput::Second(100);
193        assert!(matches!(output, SelectTwoOutput::Second(100)));
194    }
195
196    #[test]
197    fn test_select_multiple_output() {
198        let output = SelectMultipleOutput::Completed(0, 42);
199        assert!(matches!(output, SelectMultipleOutput::Completed(0, 42)));
200    }
201
202    #[test]
203    fn test_ready_future() {
204        // Test a future that's immediately ready
205        // 测试立即就绪的future
206        struct Ready;
207
208        impl Future for Ready {
209            type Output = i32;
210
211            fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
212                Poll::Ready(42)
213            }
214        }
215
216        let noop_waker = Waker::noop();
217        let mut context = Context::from_waker(&noop_waker);
218
219        let mut future = Box::pin(Ready);
220        assert!(matches!(Pin::new(&mut future).poll(&mut context), Poll::Ready(42)));
221    }
222}