1 // Copyright 2020 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //! An Executor and future combinators based on operations that block on file descriptors.
6 //!
7 //! This crate is meant to be used with the `futures-rs` crate that provides further combinators
8 //! and utility functions to combine and manage futures. All futures will run until they block on a
9 //! file descriptor becoming readable or writable. Facilities are provided to register future
10 //! wakers based on such events.
11 //!
12 //! # Running top-level futures.
13 //!
14 //! Use helper functions based the desired behavior of your application.
15 //!
16 //! ## Running one future.
17 //!
18 //! If there is only one top-level future to run, use the [`run_one`](fn.run_one.html) function.
19 //!
20 //! ## Completing one of several futures.
21 //!
22 //! If there are several top level tasks that should run until any one completes, use the "select"
23 //! family of executor constructors. These return an [`Executor`](trait.Executor.html) whose `run`
24 //! function will return when the first future completes. The uncompleted futures will also be
25 //! returned so they can be run further or otherwise cleaned up. These functions are inspired by
26 //! the `select_all` function from futures-rs, but built to be run inside an FD based executor and
27 //! to poll only when necessary. See the docs for [`select2`](fn.select2.html),
28 //! [`select3`](fn.select3.html), [`select4`](fn.select4.html), and [`select5`](fn.select5.html).
29 //!
30 //! ## Completing all of several futures.
31 //!
32 //! If there are several top level tasks that all need to be completed, use the "complete" family
33 //! of executor constructors. These return an [`Executor`](trait.Executor.html) whose `run`
34 //! function will return only once all the futures passed to it have completed. These functions are
35 //! inspired by the `join_all` function from futures-rs, but built to be run inside an FD based
36 //! executor and to poll only when necessary. See the docs for [`complete2`](fn.complete2.html),
37 //! [`complete3`](fn.complete3.html), [`complete4`](fn.complete4.html), and
38 //! [`complete5`](fn.complete5.html).
39 //!
40 //! # Implementing new FD-based futures.
41 //!
42 //! For URing implementations should provide an implementation of the `IoSource` trait.
43 //! For the FD executor, new futures can use the existing ability to poll a source to build async
44 //! functionality on top of.
45 //!
46 //! # Implementations
47 //!
48 //! Currently there are two paths for using the asynchronous IO. One uses a WaitContext and drives
49 //! futures based on the FDs signaling they are ready for the opteration. This method will exist so
50 //! long as kernels < 5.4 are supported.
51 //! The other method submits operations to io_uring and is signaled when they complete. This is more
52 //! efficient, but only supported on kernel 5.4+.
53 //! If `IoSource::new` is used to interface with async IO, then the correct backend will be chosen
54 //! automatically.
55 //!
56 //! # Examples
57 //!
58 //! See the docs for `IoSource` if support for kernels <5.4 is required. Focus on `UringSource` if
59 //! all systems have support for io_uring.
60
61 mod async_types;
62 pub mod audio_streams_async;
63 mod blocking;
64 mod complete;
65 mod event;
66 mod io_ext;
67 mod io_source;
68 pub mod mem;
69 mod queue;
70 mod select;
71 pub mod sync;
72 pub mod sys;
73 pub use sys::Executor;
74 pub use sys::ExecutorKind;
75 pub use sys::TaskHandle;
76 mod timer;
77 mod waker;
78
79 use std::future::Future;
80 use std::pin::Pin;
81 use std::task::Poll;
82
83 pub use async_types::*;
84 pub use base::Event;
85 #[cfg(unix)]
86 pub use blocking::sys::unix::block_on::block_on;
87 pub use blocking::unblock;
88 pub use blocking::unblock_disarm;
89 pub use blocking::BlockingPool;
90 pub use blocking::CancellableBlockingPool;
91 pub use blocking::TimeoutAction;
92 pub use event::EventAsync;
93 #[cfg(windows)]
94 pub use futures::executor::block_on;
95 use futures::stream::FuturesUnordered;
96 pub use io_ext::AsyncWrapper;
97 pub use io_ext::Error as AsyncError;
98 pub use io_ext::IntoAsync;
99 pub use io_ext::Result as AsyncResult;
100 pub use io_source::AllocateMode;
101 pub use io_source::IoSource;
102 pub use mem::BackingMemory;
103 pub use mem::MemRegion;
104 pub use mem::VecIoWrapper;
105 use remain::sorted;
106 pub use select::SelectResult;
107 pub use sys::run_one;
108 use thiserror::Error as ThisError;
109 pub use timer::TimerAsync;
110
111 #[sorted]
112 #[derive(ThisError, Debug)]
113 pub enum Error {
114 /// Error from EventAsync
115 #[error("Failure in EventAsync: {0}")]
116 EventAsync(base::Error),
117 /// Error from the handle executor.
118 #[cfg(windows)]
119 #[error("Failure in the handle executor: {0}")]
120 HandleExecutor(sys::windows::handle_executor::Error),
121 /// Error from the polled(FD) source, which includes error from the FD executor.
122 #[cfg(unix)]
123 #[error("An error with a poll source: {0}")]
124 PollSource(sys::unix::poll_source::Error),
125 /// Error from Timer.
126 #[error("Failure in Timer: {0}")]
127 Timer(base::Error),
128 /// Error from TimerFd.
129 #[error("Failure in TimerAsync: {0}")]
130 TimerAsync(AsyncError),
131 /// Error from the uring executor.
132 #[cfg(unix)]
133 #[error("Failure in the uring executor: {0}")]
134 URingExecutor(sys::unix::uring_executor::Error),
135 }
136 pub type Result<T> = std::result::Result<T, Error>;
137
138 /// Heterogeneous collection of `async_task:Task` that are running in a "detached" state.
139 ///
140 /// We keep them around to ensure they are dropped before the executor they are running on.
141 pub(crate) struct DetachedTasks(FuturesUnordered<Pin<Box<dyn Future<Output = ()> + Send>>>);
142
143 impl DetachedTasks {
new() -> Self144 pub(crate) fn new() -> Self {
145 DetachedTasks(FuturesUnordered::new())
146 }
147
push<R: Send + 'static>(&self, task: async_task::Task<R>)148 pub(crate) fn push<R: Send + 'static>(&self, task: async_task::Task<R>) {
149 // Convert to fallible, otherwise poll could panic if the `Runnable` is dropped early.
150 let task = task.fallible();
151 self.0.push(Box::pin(async {
152 let _ = task.await;
153 }));
154 }
155
156 /// Polls all the tasks, dropping any that complete.
poll(&mut self, cx: &mut std::task::Context)157 pub(crate) fn poll(&mut self, cx: &mut std::task::Context) {
158 use futures::Stream;
159 while let Poll::Ready(Some(_)) = Pin::new(&mut self.0).poll_next(cx) {}
160 }
161 }
162
163 // Select helpers to run until any future completes.
164
165 /// Creates a combinator that runs the two given futures until one completes, returning a tuple
166 /// containing the result of the finished future and the still pending future.
167 ///
168 /// # Example
169 ///
170 /// ```
171 /// use cros_async::{SelectResult, select2, run_one};
172 /// use futures::future::pending;
173 /// use futures::pin_mut;
174 ///
175 /// let first = async {5};
176 /// let second = async {let () = pending().await;};
177 /// pin_mut!(first);
178 /// pin_mut!(second);
179 /// match run_one(select2(first, second)) {
180 /// Ok((SelectResult::Finished(5), SelectResult::Pending(_second))) => (),
181 /// _ => panic!("Select didn't return the first future"),
182 /// };
183 /// ```
select2<F1: Future + Unpin, F2: Future + Unpin>( f1: F1, f2: F2, ) -> (SelectResult<F1>, SelectResult<F2>)184 pub async fn select2<F1: Future + Unpin, F2: Future + Unpin>(
185 f1: F1,
186 f2: F2,
187 ) -> (SelectResult<F1>, SelectResult<F2>) {
188 select::Select2::new(f1, f2).await
189 }
190
191 /// Creates a combinator that runs the three given futures until one or more completes, returning a
192 /// tuple containing the result of the finished future(s) and the still pending future(s).
193 ///
194 /// # Example
195 ///
196 /// ```
197 /// use cros_async::{SelectResult, select3, run_one};
198 /// use futures::future::pending;
199 /// use futures::pin_mut;
200 ///
201 /// let first = async {4};
202 /// let second = async {let () = pending().await;};
203 /// let third = async {5};
204 /// pin_mut!(first);
205 /// pin_mut!(second);
206 /// pin_mut!(third);
207 /// match run_one(select3(first, second, third)) {
208 /// Ok((SelectResult::Finished(4),
209 /// SelectResult::Pending(_second),
210 /// SelectResult::Finished(5))) => (),
211 /// _ => panic!("Select didn't return the futures"),
212 /// };
213 /// ```
select3<F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin>( f1: F1, f2: F2, f3: F3, ) -> (SelectResult<F1>, SelectResult<F2>, SelectResult<F3>)214 pub async fn select3<F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin>(
215 f1: F1,
216 f2: F2,
217 f3: F3,
218 ) -> (SelectResult<F1>, SelectResult<F2>, SelectResult<F3>) {
219 select::Select3::new(f1, f2, f3).await
220 }
221
222 /// Creates a combinator that runs the four given futures until one or more completes, returning a
223 /// tuple containing the result of the finished future(s) and the still pending future(s).
224 ///
225 /// # Example
226 ///
227 /// ```
228 /// use cros_async::{SelectResult, select4, run_one};
229 /// use futures::future::pending;
230 /// use futures::pin_mut;
231 ///
232 /// let first = async {4};
233 /// let second = async {let () = pending().await;};
234 /// let third = async {5};
235 /// let fourth = async {let () = pending().await;};
236 /// pin_mut!(first);
237 /// pin_mut!(second);
238 /// pin_mut!(third);
239 /// pin_mut!(fourth);
240 /// match run_one(select4(first, second, third, fourth)) {
241 /// Ok((SelectResult::Finished(4), SelectResult::Pending(_second),
242 /// SelectResult::Finished(5), SelectResult::Pending(_fourth))) => (),
243 /// _ => panic!("Select didn't return the futures"),
244 /// };
245 /// ```
select4< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, )246 pub async fn select4<
247 F1: Future + Unpin,
248 F2: Future + Unpin,
249 F3: Future + Unpin,
250 F4: Future + Unpin,
251 >(
252 f1: F1,
253 f2: F2,
254 f3: F3,
255 f4: F4,
256 ) -> (
257 SelectResult<F1>,
258 SelectResult<F2>,
259 SelectResult<F3>,
260 SelectResult<F4>,
261 ) {
262 select::Select4::new(f1, f2, f3, f4).await
263 }
264
265 /// Creates a combinator that runs the five given futures until one or more completes, returning a
266 /// tuple containing the result of the finished future(s) and the still pending future(s).
267 ///
268 /// # Example
269 ///
270 /// ```
271 /// use cros_async::{SelectResult, select5, run_one};
272 /// use futures::future::pending;
273 /// use futures::pin_mut;
274 ///
275 /// let first = async {4};
276 /// let second = async {let () = pending().await;};
277 /// let third = async {5};
278 /// let fourth = async {let () = pending().await;};
279 /// let fifth = async {6};
280 /// pin_mut!(first);
281 /// pin_mut!(second);
282 /// pin_mut!(third);
283 /// pin_mut!(fourth);
284 /// pin_mut!(fifth);
285 /// match run_one(select5(first, second, third, fourth, fifth)) {
286 /// Ok((SelectResult::Finished(4), SelectResult::Pending(_second),
287 /// SelectResult::Finished(5), SelectResult::Pending(_fourth),
288 /// SelectResult::Finished(6))) => (),
289 /// _ => panic!("Select didn't return the futures"),
290 /// };
291 /// ```
select5< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, F5: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, SelectResult<F5>, )292 pub async fn select5<
293 F1: Future + Unpin,
294 F2: Future + Unpin,
295 F3: Future + Unpin,
296 F4: Future + Unpin,
297 F5: Future + Unpin,
298 >(
299 f1: F1,
300 f2: F2,
301 f3: F3,
302 f4: F4,
303 f5: F5,
304 ) -> (
305 SelectResult<F1>,
306 SelectResult<F2>,
307 SelectResult<F3>,
308 SelectResult<F4>,
309 SelectResult<F5>,
310 ) {
311 select::Select5::new(f1, f2, f3, f4, f5).await
312 }
313
314 /// Creates a combinator that runs the six given futures until one or more completes, returning a
315 /// tuple containing the result of the finished future(s) and the still pending future(s).
316 ///
317 /// # Example
318 ///
319 /// ```
320 /// use cros_async::{SelectResult, select6, run_one};
321 /// use futures::future::pending;
322 /// use futures::pin_mut;
323 ///
324 /// let first = async {1};
325 /// let second = async {let () = pending().await;};
326 /// let third = async {3};
327 /// let fourth = async {let () = pending().await;};
328 /// let fifth = async {5};
329 /// let sixth = async {6};
330 /// pin_mut!(first);
331 /// pin_mut!(second);
332 /// pin_mut!(third);
333 /// pin_mut!(fourth);
334 /// pin_mut!(fifth);
335 /// pin_mut!(sixth);
336 /// match run_one(select6(first, second, third, fourth, fifth, sixth)) {
337 /// Ok((SelectResult::Finished(1), SelectResult::Pending(_second),
338 /// SelectResult::Finished(3), SelectResult::Pending(_fourth),
339 /// SelectResult::Finished(5), SelectResult::Finished(6))) => (),
340 /// _ => panic!("Select didn't return the futures"),
341 /// };
342 /// ```
select6< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, F5: Future + Unpin, F6: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, f6: F6, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, SelectResult<F5>, SelectResult<F6>, )343 pub async fn select6<
344 F1: Future + Unpin,
345 F2: Future + Unpin,
346 F3: Future + Unpin,
347 F4: Future + Unpin,
348 F5: Future + Unpin,
349 F6: Future + Unpin,
350 >(
351 f1: F1,
352 f2: F2,
353 f3: F3,
354 f4: F4,
355 f5: F5,
356 f6: F6,
357 ) -> (
358 SelectResult<F1>,
359 SelectResult<F2>,
360 SelectResult<F3>,
361 SelectResult<F4>,
362 SelectResult<F5>,
363 SelectResult<F6>,
364 ) {
365 select::Select6::new(f1, f2, f3, f4, f5, f6).await
366 }
367
select7< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, F5: Future + Unpin, F6: Future + Unpin, F7: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, f6: F6, f7: F7, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, SelectResult<F5>, SelectResult<F6>, SelectResult<F7>, )368 pub async fn select7<
369 F1: Future + Unpin,
370 F2: Future + Unpin,
371 F3: Future + Unpin,
372 F4: Future + Unpin,
373 F5: Future + Unpin,
374 F6: Future + Unpin,
375 F7: Future + Unpin,
376 >(
377 f1: F1,
378 f2: F2,
379 f3: F3,
380 f4: F4,
381 f5: F5,
382 f6: F6,
383 f7: F7,
384 ) -> (
385 SelectResult<F1>,
386 SelectResult<F2>,
387 SelectResult<F3>,
388 SelectResult<F4>,
389 SelectResult<F5>,
390 SelectResult<F6>,
391 SelectResult<F7>,
392 ) {
393 select::Select7::new(f1, f2, f3, f4, f5, f6, f7).await
394 }
395
select8< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, F5: Future + Unpin, F6: Future + Unpin, F7: Future + Unpin, F8: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, f6: F6, f7: F7, f8: F8, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, SelectResult<F5>, SelectResult<F6>, SelectResult<F7>, SelectResult<F8>, )396 pub async fn select8<
397 F1: Future + Unpin,
398 F2: Future + Unpin,
399 F3: Future + Unpin,
400 F4: Future + Unpin,
401 F5: Future + Unpin,
402 F6: Future + Unpin,
403 F7: Future + Unpin,
404 F8: Future + Unpin,
405 >(
406 f1: F1,
407 f2: F2,
408 f3: F3,
409 f4: F4,
410 f5: F5,
411 f6: F6,
412 f7: F7,
413 f8: F8,
414 ) -> (
415 SelectResult<F1>,
416 SelectResult<F2>,
417 SelectResult<F3>,
418 SelectResult<F4>,
419 SelectResult<F5>,
420 SelectResult<F6>,
421 SelectResult<F7>,
422 SelectResult<F8>,
423 ) {
424 select::Select8::new(f1, f2, f3, f4, f5, f6, f7, f8).await
425 }
426
select9< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, F5: Future + Unpin, F6: Future + Unpin, F7: Future + Unpin, F8: Future + Unpin, F9: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, f6: F6, f7: F7, f8: F8, f9: F9, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, SelectResult<F5>, SelectResult<F6>, SelectResult<F7>, SelectResult<F8>, SelectResult<F9>, )427 pub async fn select9<
428 F1: Future + Unpin,
429 F2: Future + Unpin,
430 F3: Future + Unpin,
431 F4: Future + Unpin,
432 F5: Future + Unpin,
433 F6: Future + Unpin,
434 F7: Future + Unpin,
435 F8: Future + Unpin,
436 F9: Future + Unpin,
437 >(
438 f1: F1,
439 f2: F2,
440 f3: F3,
441 f4: F4,
442 f5: F5,
443 f6: F6,
444 f7: F7,
445 f8: F8,
446 f9: F9,
447 ) -> (
448 SelectResult<F1>,
449 SelectResult<F2>,
450 SelectResult<F3>,
451 SelectResult<F4>,
452 SelectResult<F5>,
453 SelectResult<F6>,
454 SelectResult<F7>,
455 SelectResult<F8>,
456 SelectResult<F9>,
457 ) {
458 select::Select9::new(f1, f2, f3, f4, f5, f6, f7, f8, f9).await
459 }
460
select10< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, F5: Future + Unpin, F6: Future + Unpin, F7: Future + Unpin, F8: Future + Unpin, F9: Future + Unpin, F10: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, f6: F6, f7: F7, f8: F8, f9: F9, f10: F10, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, SelectResult<F5>, SelectResult<F6>, SelectResult<F7>, SelectResult<F8>, SelectResult<F9>, SelectResult<F10>, )461 pub async fn select10<
462 F1: Future + Unpin,
463 F2: Future + Unpin,
464 F3: Future + Unpin,
465 F4: Future + Unpin,
466 F5: Future + Unpin,
467 F6: Future + Unpin,
468 F7: Future + Unpin,
469 F8: Future + Unpin,
470 F9: Future + Unpin,
471 F10: Future + Unpin,
472 >(
473 f1: F1,
474 f2: F2,
475 f3: F3,
476 f4: F4,
477 f5: F5,
478 f6: F6,
479 f7: F7,
480 f8: F8,
481 f9: F9,
482 f10: F10,
483 ) -> (
484 SelectResult<F1>,
485 SelectResult<F2>,
486 SelectResult<F3>,
487 SelectResult<F4>,
488 SelectResult<F5>,
489 SelectResult<F6>,
490 SelectResult<F7>,
491 SelectResult<F8>,
492 SelectResult<F9>,
493 SelectResult<F10>,
494 ) {
495 select::Select10::new(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10).await
496 }
497
select11< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, F5: Future + Unpin, F6: Future + Unpin, F7: Future + Unpin, F8: Future + Unpin, F9: Future + Unpin, F10: Future + Unpin, F11: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, f6: F6, f7: F7, f8: F8, f9: F9, f10: F10, f11: F11, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, SelectResult<F5>, SelectResult<F6>, SelectResult<F7>, SelectResult<F8>, SelectResult<F9>, SelectResult<F10>, SelectResult<F11>, )498 pub async fn select11<
499 F1: Future + Unpin,
500 F2: Future + Unpin,
501 F3: Future + Unpin,
502 F4: Future + Unpin,
503 F5: Future + Unpin,
504 F6: Future + Unpin,
505 F7: Future + Unpin,
506 F8: Future + Unpin,
507 F9: Future + Unpin,
508 F10: Future + Unpin,
509 F11: Future + Unpin,
510 >(
511 f1: F1,
512 f2: F2,
513 f3: F3,
514 f4: F4,
515 f5: F5,
516 f6: F6,
517 f7: F7,
518 f8: F8,
519 f9: F9,
520 f10: F10,
521 f11: F11,
522 ) -> (
523 SelectResult<F1>,
524 SelectResult<F2>,
525 SelectResult<F3>,
526 SelectResult<F4>,
527 SelectResult<F5>,
528 SelectResult<F6>,
529 SelectResult<F7>,
530 SelectResult<F8>,
531 SelectResult<F9>,
532 SelectResult<F10>,
533 SelectResult<F11>,
534 ) {
535 select::Select11::new(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11).await
536 }
537
select12< F1: Future + Unpin, F2: Future + Unpin, F3: Future + Unpin, F4: Future + Unpin, F5: Future + Unpin, F6: Future + Unpin, F7: Future + Unpin, F8: Future + Unpin, F9: Future + Unpin, F10: Future + Unpin, F11: Future + Unpin, F12: Future + Unpin, >( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, f6: F6, f7: F7, f8: F8, f9: F9, f10: F10, f11: F11, f12: F12, ) -> ( SelectResult<F1>, SelectResult<F2>, SelectResult<F3>, SelectResult<F4>, SelectResult<F5>, SelectResult<F6>, SelectResult<F7>, SelectResult<F8>, SelectResult<F9>, SelectResult<F10>, SelectResult<F11>, SelectResult<F12>, )538 pub async fn select12<
539 F1: Future + Unpin,
540 F2: Future + Unpin,
541 F3: Future + Unpin,
542 F4: Future + Unpin,
543 F5: Future + Unpin,
544 F6: Future + Unpin,
545 F7: Future + Unpin,
546 F8: Future + Unpin,
547 F9: Future + Unpin,
548 F10: Future + Unpin,
549 F11: Future + Unpin,
550 F12: Future + Unpin,
551 >(
552 f1: F1,
553 f2: F2,
554 f3: F3,
555 f4: F4,
556 f5: F5,
557 f6: F6,
558 f7: F7,
559 f8: F8,
560 f9: F9,
561 f10: F10,
562 f11: F11,
563 f12: F12,
564 ) -> (
565 SelectResult<F1>,
566 SelectResult<F2>,
567 SelectResult<F3>,
568 SelectResult<F4>,
569 SelectResult<F5>,
570 SelectResult<F6>,
571 SelectResult<F7>,
572 SelectResult<F8>,
573 SelectResult<F9>,
574 SelectResult<F10>,
575 SelectResult<F11>,
576 SelectResult<F12>,
577 ) {
578 select::Select12::new(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12).await
579 }
580
581 // Combination helpers to run until all futures are complete.
582
583 /// Creates a combinator that runs the two given futures to completion, returning a tuple of the
584 /// outputs each yields.
585 ///
586 /// # Example
587 ///
588 /// ```
589 /// use cros_async::{complete2, run_one};
590 ///
591 /// let first = async {5};
592 /// let second = async {6};
593 /// assert_eq!(run_one(complete2(first, second)).unwrap_or((0,0)), (5,6));
594 /// ```
complete2<F1, F2>(f1: F1, f2: F2) -> (F1::Output, F2::Output) where F1: Future, F2: Future,595 pub async fn complete2<F1, F2>(f1: F1, f2: F2) -> (F1::Output, F2::Output)
596 where
597 F1: Future,
598 F2: Future,
599 {
600 complete::Complete2::new(f1, f2).await
601 }
602
603 /// Creates a combinator that runs the three given futures to completion, returning a tuple of the
604 /// outputs each yields.
605 ///
606 /// # Example
607 ///
608 /// ```
609 /// use cros_async::{complete3, run_one};
610 ///
611 /// let first = async {5};
612 /// let second = async {6};
613 /// let third = async {7};
614 /// assert_eq!(run_one(complete3(first, second, third)).unwrap_or((0,0,0)), (5,6,7));
615 /// ```
complete3<F1, F2, F3>(f1: F1, f2: F2, f3: F3) -> (F1::Output, F2::Output, F3::Output) where F1: Future, F2: Future, F3: Future,616 pub async fn complete3<F1, F2, F3>(f1: F1, f2: F2, f3: F3) -> (F1::Output, F2::Output, F3::Output)
617 where
618 F1: Future,
619 F2: Future,
620 F3: Future,
621 {
622 complete::Complete3::new(f1, f2, f3).await
623 }
624
625 /// Creates a combinator that runs the four given futures to completion, returning a tuple of the
626 /// outputs each yields.
627 ///
628 /// # Example
629 ///
630 /// ```
631 /// use cros_async::{complete4, run_one};
632 ///
633 /// let first = async {5};
634 /// let second = async {6};
635 /// let third = async {7};
636 /// let fourth = async {8};
637 /// assert_eq!(run_one(complete4(first, second, third, fourth)).unwrap_or((0,0,0,0)), (5,6,7,8));
638 /// ```
complete4<F1, F2, F3, F4>( f1: F1, f2: F2, f3: F3, f4: F4, ) -> (F1::Output, F2::Output, F3::Output, F4::Output) where F1: Future, F2: Future, F3: Future, F4: Future,639 pub async fn complete4<F1, F2, F3, F4>(
640 f1: F1,
641 f2: F2,
642 f3: F3,
643 f4: F4,
644 ) -> (F1::Output, F2::Output, F3::Output, F4::Output)
645 where
646 F1: Future,
647 F2: Future,
648 F3: Future,
649 F4: Future,
650 {
651 complete::Complete4::new(f1, f2, f3, f4).await
652 }
653
654 /// Creates a combinator that runs the five given futures to completion, returning a tuple of the
655 /// outputs each yields.
656 ///
657 /// # Example
658 ///
659 /// ```
660 /// use cros_async::{complete5, run_one};
661 ///
662 /// let first = async {5};
663 /// let second = async {6};
664 /// let third = async {7};
665 /// let fourth = async {8};
666 /// let fifth = async {9};
667 /// assert_eq!(run_one(complete5(first, second, third, fourth, fifth)).unwrap_or((0,0,0,0,0)),
668 /// (5,6,7,8,9));
669 /// ```
complete5<F1, F2, F3, F4, F5>( f1: F1, f2: F2, f3: F3, f4: F4, f5: F5, ) -> (F1::Output, F2::Output, F3::Output, F4::Output, F5::Output) where F1: Future, F2: Future, F3: Future, F4: Future, F5: Future,670 pub async fn complete5<F1, F2, F3, F4, F5>(
671 f1: F1,
672 f2: F2,
673 f3: F3,
674 f4: F4,
675 f5: F5,
676 ) -> (F1::Output, F2::Output, F3::Output, F4::Output, F5::Output)
677 where
678 F1: Future,
679 F2: Future,
680 F3: Future,
681 F4: Future,
682 F5: Future,
683 {
684 complete::Complete5::new(f1, f2, f3, f4, f5).await
685 }
686