• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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