Skip to main content

Task

Trait Task 

Source
pub trait Task<S: ?Sized = ()>: Sized {
    type Cont;
    type Break;
    type Output;

    // Required methods
    fn poll_progress(
        self: Pin<&mut Self>,
        strategy: &mut S,
        cx: &mut Context<'_>,
    ) -> Poll<ControlFlow<Self::Break, Self::Cont>>;
    fn transform_cont(
        task: BorrowedMut<'_, Self>,
        strategy: &mut S,
        value: Self::Cont,
    ) -> Option<Self::Output>;
    fn transform_break(
        task: Removed<Self>,
        strategy: &mut S,
        value: Self::Break,
    ) -> Option<Self::Output>;
}
Expand description

Asynchronous task that can be polled with strategy S.

Strategy parameter allows for:

  1. Convenient blanket implementations on external types (Futures and Streams)
  2. Multiple implementations on a single type
  3. Exposing shared data to the task

Unless you want to customize Selector’s behavior, you don’t have to manually implement this trait. You can use one of ready-to-go strategies from strategy.

§Custom task example

The example below polls a set of UdpSockets for incoming datagrams.

Note that:

  1. UdpSocket is an external type, and so is this trait (from the perspective of the implementing crate). The local strategy type makes the implementation possible.
  2. The strategy holds the receive buffer, so the whole selector needs only one, no matter how many sockets it holds. Each datagram is copied out of the shared buffer in Task::transform_cont, before the next poll can overwrite it.
  3. A failed socket is removed from the selector, because the failure is reported with ControlFlow::Break.
/// Receive buffer shared by all sockets in the selector.
///
/// Large enough to hold any datagram.
struct RecvBuffer(Box<[MaybeUninit<u8>; u16::MAX as usize]>);

impl Task<RecvBuffer> for UdpSocket {
    /// Address of the peer and length of the datagram,
    /// which sits in the shared buffer.
    type Cont = (SocketAddr, Vec<u8>);
    /// Fatal socket error.
    type Break = io::Error;
    type Output = io::Result<(SocketAddr, Vec<u8>)>;

    fn poll_progress(
        self: Pin<&mut Self>,
        buffer: &mut RecvBuffer,
        cx: &mut Context<'_>,
    ) -> Poll<ControlFlow<Self::Break, Self::Cont>> {
        let mut buf = ReadBuf::uninit(buffer.0.as_mut_slice());
        match ready!(self.poll_recv_from(cx, &mut buf)) {
            Ok(peer) => Poll::Ready(ControlFlow::Continue((peer, buf.filled().to_vec()))),
            Err(error) => Poll::Ready(ControlFlow::Break(error)),
        }
    }

    fn transform_cont(
        _: BorrowedMut<'_, Self>,
        buffer: &mut RecvBuffer,
        value: Self::Cont,
    ) -> Option<Self::Output> {
        Some(Ok(value))
    }

    fn transform_break(
        _: Removed<Self>,
        _: &mut RecvBuffer,
        error: Self::Break,
    ) -> Option<Self::Output> {
        Some(Err(error))
    }
}

let mut selector = Selector::new(RecvBuffer(Box::new([MaybeUninit::uninit(); u16::MAX as usize])));
let mut addrs = Vec::new();
for _ in 0..2 {
    let socket = UdpSocket::bind("127.0.0.1:0").await?;
    addrs.push(socket.local_addr()?);
    selector.push(socket);
}

let sender = UdpSocket::bind("127.0.0.1:0").await?;
for addr in &addrs {
    sender.send_to(b"hello", addr).await?;
    let (peer, data) = selector.next().await.unwrap()?;
    assert_eq!(peer, sender.local_addr()?);
    assert_eq!(data, b"hello");
}

Required Associated Types§

Source

type Cont

Type returned from Self::poll_progress when the task produces some value, but has not finished yet.

Source

type Break

Type returned from Self::poll_progress when the task produces its last value.

Source

type Output

Required Methods§

Source

fn poll_progress( self: Pin<&mut Self>, strategy: &mut S, cx: &mut Context<'_>, ) -> Poll<ControlFlow<Self::Break, Self::Cont>>

Polls progress on this task using the given strategy.

§Returns
Source

fn transform_cont( task: BorrowedMut<'_, Self>, strategy: &mut S, value: Self::Cont, ) -> Option<Self::Output>

Transforms Self::Cont value obtained from Self::poll_progress into the final value type Self::Output.

This is the place to:

  1. Enrich the value with some properties of the task, passed as BorrowedMut
  2. Silently ignore the value by returning None
Source

fn transform_break( task: Removed<Self>, strategy: &mut S, value: Self::Break, ) -> Option<Self::Output>

Transforms Self::Break value obtained from Self::poll_progress into the final value type Self::Output.

This is the place to:

  1. Enrich the value with some properties of the task, passed as Removed
  2. Silently ignore the value by returning None

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl<F: Future> Task<FutureBasic> for F

Source§

impl<F: Future> Task<FutureReclaim> for F

Source§

impl<S, T> Task<&mut S> for T
where S: ?Sized, T: Task<S>,

Source§

type Cont = <T as Task<S>>::Cont

Source§

type Break = <T as Task<S>>::Break

Source§

type Output = <T as Task<S>>::Output

Source§

impl<S, T> Task<Box<S>> for T
where S: ?Sized, T: Task<S>,

Source§

type Cont = <T as Task<S>>::Cont

Source§

type Break = <T as Task<S>>::Break

Source§

type Output = <T as Task<S>>::Output

Source§

impl<S: Stream> Task<StreamBasic> for S

Source§

type Cont = <S as Stream>::Item

Source§

type Break = ()

Source§

type Output = <S as Stream>::Item

Source§

impl<S: Stream> Task<StreamReclaim> for S

Source§

type Cont = <S as Stream>::Item

Source§

type Break = ()

Source§

type Output = ControlFlow<Removed<S>, (Id<S>, <S as Stream>::Item)>

Source§

impl<S: Stream> Task<StreamWithId> for S

Source§

type Cont = <S as Stream>::Item

Source§

type Break = ()

Source§

type Output = (Id<S>, <S as Stream>::Item)

Source§

impl<S: TryStream> Task<TryStreamBasic> for S

Source§

impl<S: TryStream> Task<TryStreamReclaim> for S

Source§

type Cont = <S as TryStream>::Ok

Source§

type Break = Result<(), <S as TryStream>::Error>

Source§

type Output = ControlFlow<(Removed<S>, Result<(), <S as TryStream>::Error>), (Id<S>, <S as TryStream>::Ok)>

Source§

impl<S: TryStream> Task<TryStreamWithId> for S

Source§

type Cont = <S as TryStream>::Ok

Source§

type Break = Result<(), <S as TryStream>::Error>

Source§

type Output = (Id<S>, Result<<S as TryStream>::Ok, <S as TryStream>::Error>)