jlrs/runtime/handle/async_handle/
dispatch.rs

1//! Dispatch a task to the async runtime.
2
3use std::fmt;
4
5use async_channel::{SendError, Sender, TrySendError};
6
7use super::channel::OneshotReceiver;
8use crate::{
9    error::{JlrsError, RuntimeError},
10    prelude::JlrsResult,
11};
12
13/// Dispatch a task to the async runtime.
14pub struct Dispatch<'a, M, T> {
15    msg: M,
16    sender: &'a Sender<M>,
17    receiver: OneshotReceiver<T>,
18}
19
20impl<'a, M, T> Dispatch<'a, M, T> {
21    #[inline]
22    pub(crate) const fn new(msg: M, sender: &'a Sender<M>, receiver: OneshotReceiver<T>) -> Self {
23        Dispatch {
24            msg,
25            sender,
26            receiver,
27        }
28    }
29
30    /// Dispatch the task.
31    pub async fn dispatch(self) -> JlrsResult<OneshotReceiver<T>> {
32        match self.sender.send(self.msg).await {
33            Ok(_) => Ok(self.receiver),
34            Err(SendError(_)) => Err(RuntimeError::ChannelClosed)?,
35        }
36    }
37
38    /// Try to dispatch the task.
39    ///
40    /// If the channel is full, the dispatcher is returned to allow retrying.
41    pub fn try_dispatch(self) -> Result<OneshotReceiver<T>, JlrsResult<Self>> {
42        match self.sender.try_send(self.msg) {
43            Ok(_) => Ok(self.receiver),
44            Err(TrySendError::Closed(_)) => Err(Err(Box::new(JlrsError::RuntimeError(
45                RuntimeError::ChannelClosed,
46            )))),
47            Err(TrySendError::Full(msg)) => Err(Ok(Dispatch {
48                msg,
49                sender: self.sender,
50                receiver: self.receiver,
51            })),
52        }
53    }
54}
55
56impl<'a, M, T> fmt::Debug for Dispatch<'a, M, T> {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        f.debug_struct("Dispatch").finish()
59    }
60}