2023-09-10 03:03:49 +02:00
|
|
|
//! # Controller
|
|
|
|
//!
|
2023-09-10 03:39:44 +02:00
|
|
|
//! an bidirectional stream handler to easily manage async operations across local buffers and the
|
|
|
|
//! server
|
2023-09-10 03:03:49 +02:00
|
|
|
|
|
|
|
use crate::Result;
|
|
|
|
|
2023-09-10 03:40:31 +02:00
|
|
|
#[async_trait::async_trait]
|
2023-09-10 03:03:49 +02:00
|
|
|
pub(crate) trait ControllerWorker<T : Sized + Send + Sync> {
|
|
|
|
type Controller : Controller<T>;
|
|
|
|
type Tx;
|
|
|
|
type Rx;
|
|
|
|
|
2024-08-08 02:27:06 +02:00
|
|
|
fn controller(&self) -> Self::Controller;
|
2023-09-10 03:03:49 +02:00
|
|
|
async fn work(self, tx: Self::Tx, rx: Self::Rx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// async and threadsafe handle to a generic bidirectional stream
|
2023-09-10 03:39:44 +02:00
|
|
|
///
|
|
|
|
/// this generic trait is implemented by actors managing stream procedures.
|
|
|
|
/// events can be enqueued for dispatching without blocking ([Controller::send]), and an async blocking
|
2024-02-09 01:16:16 +01:00
|
|
|
/// api ([Controller::recv]) is provided to wait for server events.
|
2023-09-10 03:39:44 +02:00
|
|
|
///
|
2023-11-17 05:47:40 +01:00
|
|
|
/// * if possible, prefer a pure [Controller::recv] consumer, awaiting for events
|
|
|
|
/// * if async is not feasible a [Controller::poll]/[Controller::try_recv] approach is possible
|
2023-09-10 03:40:31 +02:00
|
|
|
#[async_trait::async_trait]
|
2023-09-10 03:03:49 +02:00
|
|
|
pub trait Controller<T : Sized + Send + Sync> : Sized + Send + Sync {
|
2023-11-17 05:47:40 +01:00
|
|
|
/// enqueue a new value to be sent to all other users
|
|
|
|
///
|
|
|
|
/// success or failure of this function does not imply validity of sent operation,
|
|
|
|
/// because it's integrated asynchronously on the background worker
|
2024-08-14 15:54:32 +02:00
|
|
|
async fn send(&self, x: T) -> Result<()>;
|
2023-09-10 03:03:49 +02:00
|
|
|
|
2023-11-17 05:47:40 +01:00
|
|
|
/// get next value from other users, blocking until one is available
|
2023-09-10 03:03:49 +02:00
|
|
|
///
|
|
|
|
/// this is just an async trait function wrapped by `async_trait`:
|
|
|
|
///
|
|
|
|
/// `async fn recv(&self) -> codemp::Result<T>;`
|
|
|
|
async fn recv(&self) -> Result<T> {
|
2024-08-14 00:24:32 +02:00
|
|
|
loop {
|
|
|
|
self.poll().await?;
|
|
|
|
if let Some(x) = self.try_recv().await? {
|
|
|
|
break Ok(x);
|
|
|
|
}
|
2023-09-10 03:03:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-15 22:47:49 +02:00
|
|
|
/// registers a callback to be called on receive.
|
|
|
|
///
|
|
|
|
/// there can only be one callback at any given time.
|
|
|
|
fn callback(&self, cb: impl Into<ControllerCallback<Self>>);
|
2024-08-15 19:32:01 +02:00
|
|
|
|
2024-08-15 22:47:49 +02:00
|
|
|
/// clears the currently registered callback.
|
2024-08-15 19:32:01 +02:00
|
|
|
fn clear_callback(&self);
|
|
|
|
|
2023-11-17 05:47:40 +01:00
|
|
|
/// block until next value is available without consuming it
|
2023-09-10 03:03:49 +02:00
|
|
|
///
|
|
|
|
/// this is just an async trait function wrapped by `async_trait`:
|
|
|
|
///
|
|
|
|
/// `async fn poll(&self) -> codemp::Result<()>;`
|
|
|
|
async fn poll(&self) -> Result<()>;
|
|
|
|
|
|
|
|
/// attempt to receive a value without blocking, return None if nothing is available
|
2024-08-14 00:24:32 +02:00
|
|
|
async fn try_recv(&self) -> Result<Option<T>>;
|
2024-08-08 00:28:15 +02:00
|
|
|
|
|
|
|
/// stop underlying worker
|
|
|
|
///
|
|
|
|
/// note that this will mean no more values can be received nor sent,
|
|
|
|
/// but existing controllers will still be accessible until all are dropped
|
|
|
|
///
|
|
|
|
/// returns true if stop signal was sent, false if channel is closed
|
|
|
|
/// (likely if worker is already stopped)
|
|
|
|
fn stop(&self) -> bool;
|
2023-09-10 03:03:49 +02:00
|
|
|
}
|
2024-08-15 19:32:01 +02:00
|
|
|
|
|
|
|
|
2024-08-15 20:15:23 +02:00
|
|
|
/// type wrapper for Boxed dyn callback
|
2024-08-15 20:41:53 +02:00
|
|
|
pub struct ControllerCallback<T>(Box<dyn Sync + Send + Fn(T)>);
|
2024-08-15 19:32:01 +02:00
|
|
|
|
2024-08-15 20:41:53 +02:00
|
|
|
impl<T> ControllerCallback<T> {
|
|
|
|
pub fn call(&self, x: T) {
|
|
|
|
self.0(x) // lmao at this syntax
|
2024-08-15 20:15:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-15 20:41:53 +02:00
|
|
|
impl<T> std::fmt::Debug for ControllerCallback<T> {
|
2024-08-15 20:15:23 +02:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(f, "ControllerCallback {{ {:p} }}", self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-15 20:41:53 +02:00
|
|
|
impl<T, X: Sync + Send + Fn(T) + 'static> From<X> for ControllerCallback<T> {
|
|
|
|
fn from(value: X) -> Self {
|
2024-08-15 20:15:23 +02:00
|
|
|
Self(Box::new(value))
|
|
|
|
}
|
|
|
|
}
|