use std::sync::Arc;
use std::ops::DerefMut;
use std::sync::mpsc;
use std::sync::TryLockError;
use std::time::Duration;
use super::*;
#[derive(Debug)]
pub enum TryDualLockError {
LeftWouldBlock,
RightWouldBlock,
LeftPoisoned,
RightPoisoned,
}
pub fn on_dual_definition<C1, C2, F, T>(
c1: &Arc<Component<C1>>,
c2: &Arc<Component<C2>>,
f: F,
) -> Result<T, TryDualLockError>
where
C1: ComponentDefinition + Sized + 'static,
C2: ComponentDefinition + Sized + 'static,
F: FnOnce(&mut C1, &mut C2) -> T,
{
let mut cd1 = c1.definition().try_lock().map_err(|e| match e {
TryLockError::Poisoned(_) => TryDualLockError::LeftPoisoned,
TryLockError::WouldBlock => TryDualLockError::LeftWouldBlock,
})?;
let mut cd2 = c2.definition().try_lock().map_err(|e| match e {
TryLockError::Poisoned(_) => TryDualLockError::RightPoisoned,
TryLockError::WouldBlock => TryDualLockError::RightWouldBlock,
})?;
Ok(f(cd1.deref_mut(), cd2.deref_mut()))
}
pub fn biconnect<P, C1, C2>(prov: &mut ProvidedPort<P, C1>, req: &mut RequiredPort<P, C2>) -> ()
where
P: Port,
C1: ComponentDefinition + Sized + 'static + Provide<P>,
C2: ComponentDefinition + Sized + 'static + Require<P>,
{
let prov_share = prov.share();
let req_share = req.share();
prov.connect(req_share);
req.connect(prov_share);
}
pub fn promise<T: Send + Sized>() -> (Promise<T>, Future<T>) {
let (tx, rx) = mpsc::channel();
let f = Future { result_channel: rx };
let p = Promise { result_channel: tx };
(p, f)
}
#[derive(Debug)]
pub enum PromiseErr {
ChannelBroken,
AlreadyFulfilled,
}
#[derive(Debug)]
pub struct Future<T: Send + Sized> {
result_channel: mpsc::Receiver<T>,
}
impl<T: Send + Sized> Future<T> {
pub fn wait(self) -> T {
self.result_channel.recv().unwrap()
}
pub fn wait_timeout(self, timeout: Duration) -> Result<T, Future<T>> {
self.result_channel.recv_timeout(timeout).map_err(|_| self)
}
}
pub trait Fulfillable<T> {
fn fulfill(self, t: T) -> Result<(), PromiseErr>;
}
#[derive(Debug)]
pub struct Promise<T: Send + Sized> {
result_channel: mpsc::Sender<T>,
}
impl<T: Send + Sized> Fulfillable<T> for Promise<T> {
fn fulfill(self, t: T) -> Result<(), PromiseErr> {
self.result_channel
.send(t)
.map_err(|_| PromiseErr::ChannelBroken)
}
}