1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
//! Dispatch a task to the async runtime.
use std::{fmt::Debug, marker::PhantomData};
use crate::{
async_util::affinity::{Affinity, ToAny, ToMain, ToWorker},
runtime::async_rt::{queue::Sender, Message},
};
/// Dispatch a task to the async runtime.
pub struct Dispatch<'a, D> {
msg: Message,
sender: &'a Sender<Message>,
_dispatch: PhantomData<D>,
}
impl<'a, D> Debug for Dispatch<'a, D> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Dispatch").finish()
}
}
impl<'a, D: Affinity> Dispatch<'a, D> {
#[inline]
pub(super) fn new(sender: &'a Sender<Message>, msg: Message) -> Self {
Dispatch {
msg,
sender,
_dispatch: PhantomData,
}
}
}
impl<'a, D: ToAny> Dispatch<'a, D> {
/// Dispatch the task to any thread.
///
/// The dispatched task can be handled by either the main thread or any of the worker threads.
/// This method doesn't resolve until the task has been successfully dispatched.
#[inline]
pub async fn dispatch_any(self) {
self.sender.send(self.msg).await
}
/// Try to dispatch the task to any thread.
///
/// The dispatched task can be handled by either the main thread or any of the worker threads.
/// If the backing queue is full, the dispatcher is returned to allow retrying.
#[inline]
pub fn try_dispatch_any(self) -> Result<(), Self> {
if let Some(msg) = self.sender.try_send(self.msg) {
Err(Dispatch {
msg,
sender: self.sender,
_dispatch: PhantomData,
})
} else {
Ok(())
}
}
}
impl<'a, D: ToMain> Dispatch<'a, D> {
/// Dispatch the task to the main thread.
///
/// The dispatched task is guaranteed to be handled by the main thread. This method doesn't
/// resolve until the task has been successfully dispatched.
#[inline]
pub async fn dispatch_main(self) {
self.sender.send_main(self.msg).await
}
/// Try to dispatch the task to the main thread.
///
/// The dispatched task is guaranteed to be handled by the main thread. If the backing queue
/// is full, the dispatcher is returned to allow retrying.
#[inline]
pub fn try_dispatch_main(self) -> Result<(), Self> {
if let Some(msg) = self.sender.try_send_main(self.msg) {
Err(Dispatch {
msg,
sender: self.sender,
_dispatch: PhantomData,
})
} else {
Ok(())
}
}
}
impl<'a, D: ToWorker> Dispatch<'a, D> {
/// Dispatch the task to a worker thread.
///
/// The dispatched task is guaranteed to be handled by a worker thread if they're used,
/// otherwise it's handled by the main thread. This method doesn't resolve until the task has
/// been successfully dispatched.
#[inline]
pub async fn dispatch_worker(self) {
self.sender.send_worker(self.msg).await
}
/// Try to dispatch the task to a worker thread.
///
/// The dispatched task is guaranteed to be handled by a worker thread if they're used,
/// otherwise it's handled by the main thread. If the backing queue is full, the dispatcher
/// is returned to allow retrying.
#[inline]
pub fn try_dispatch_worker(self) -> Result<(), Self> {
if let Some(msg) = self.sender.try_send_worker(self.msg) {
Err(Dispatch {
msg,
sender: self.sender,
_dispatch: PhantomData,
})
} else {
Ok(())
}
}
}