async_selector/pollable.rs
1//! Traits that make the [`Selector`](crate::selector::Selector) generic over asynchronous tasks and polling logic.
2//!
3//! Unless you want to exercise the full flexibility of the selector, you don't need to use these traits.
4//! You can use plain [`FutureSelector`](crate::FutureSelector) and [`StreamSelector`](crate::StreamSelector).
5
6use std::{
7 marker::PhantomData,
8 ops::ControlFlow,
9 pin::Pin,
10 task::{Context, Poll},
11};
12
13use futures::Stream;
14
15/// Determines the type of pollable task that can be stored in a [`Selector`](crate::selector::Selector).
16///
17/// This trait exists solely to enable non-conflicting blanket implementations for [`Future`]s and [`Stream`]s.
18pub trait PollStrategy {
19 /// Type of the task that will be stored in the [`Selector`](crate::selector::Selector).
20 type Pollable;
21}
22
23/// Marker trait that allows for a blanket implementation of [`PollWith`] on all [`Future`]s.
24pub struct PollAsFuture<F>(PhantomData<fn() -> F>);
25
26impl<F: Future> PollStrategy for PollAsFuture<F> {
27 type Pollable = F;
28}
29
30/// Marker trait that allows for a blanket implementation of [`PollWith`] on all [`Stream`]s.
31pub struct PollAsStream<S>(PhantomData<fn() -> S>);
32
33impl<S: Stream> PollStrategy for PollAsStream<S> {
34 type Pollable = S;
35}
36
37/// Determines how the [`Selector`](crate::selector::Selector) polls the tasks and interprets their outputs.
38pub trait PollWith<'a, E: ?Sized, EMut: ?Sized>: PollStrategy {
39 /// Type of values returned when polling the task.
40 type Progress;
41
42 /// Polls the given task, providing references to strongly typed extensions.
43 ///
44 /// # Extensions
45 ///
46 /// This method supports passing references to immutable and immutable extensions
47 /// that can be used by the task. This allows the tasks for operating on a shared state
48 /// without any unsafe code or synchronization primitives.
49 /// Even more, extensions allow for static polymorphism in the types returned by the task.
50 /// See relevant [example](https://github.com/Razz4780/async-selector/blob/main/examples/extensions.rs).
51 ///
52 /// # Returns
53 ///
54 /// * `ControlFlow::Continue` if the task has not finished and might yield more values
55 /// * `ControlFlow::Break` if the task has finished
56 fn poll_progress(
57 state: Pin<&mut Self::Pollable>,
58 ext: &'a E,
59 ext_mut: &mut EMut,
60 cx: &mut Context<'_>,
61 ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>>;
62}
63
64impl<'a, F: Future> PollWith<'a, (), ()> for PollAsFuture<F> {
65 type Progress = F::Output;
66
67 fn poll_progress(
68 state: Pin<&mut Self::Pollable>,
69 _: &'a (),
70 _: &mut (),
71 cx: &mut Context<'_>,
72 ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
73 state.poll(cx).map(Some).map(ControlFlow::Break)
74 }
75}
76
77impl<'a, S: Stream> PollWith<'a, (), ()> for PollAsStream<S> {
78 type Progress = S::Item;
79
80 fn poll_progress(
81 state: Pin<&mut Self::Pollable>,
82 _: &'a (),
83 _: &mut (),
84 cx: &mut Context<'_>,
85 ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
86 state.poll_next(cx).map(|opt| {
87 opt.map(ControlFlow::Continue)
88 .unwrap_or(ControlFlow::Break(None))
89 })
90 }
91}