Skip to main content

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}