use std::time::Duration;
use crate::{
cpu::{RxDatagram, TxDatagram},
error::AUTDInternalError,
geometry::{Device, Transducer},
};
pub trait Link<T: Transducer>: Send {
fn open(&mut self, devices: &[Device<T>]) -> Result<(), AUTDInternalError>;
fn close(&mut self) -> Result<(), AUTDInternalError>;
fn send(&mut self, tx: &TxDatagram) -> Result<bool, AUTDInternalError>;
fn receive(&mut self, rx: &mut RxDatagram) -> Result<bool, AUTDInternalError>;
fn is_open(&self) -> bool;
fn timeout(&self) -> Duration;
fn send_receive(
&mut self,
tx: &TxDatagram,
rx: &mut RxDatagram,
timeout: Duration,
) -> Result<bool, AUTDInternalError> {
if !self.send(tx)? {
return Ok(false);
}
if timeout.is_zero() {
return self.receive(rx);
}
self.wait_msg_processed(tx, rx, timeout)
}
fn update_geometry(&mut self, _: &[Device<T>]) -> Result<(), AUTDInternalError> {
Ok(())
}
fn wait_msg_processed(
&mut self,
tx: &TxDatagram,
rx: &mut RxDatagram,
timeout: Duration,
) -> Result<bool, AUTDInternalError> {
let start = std::time::Instant::now();
loop {
std::thread::sleep(std::time::Duration::from_millis(1));
if !self.receive(rx)? {
continue;
}
if tx.headers().zip(rx.iter()).all(|(h, r)| h.msg_id == r.ack) {
return Ok(true);
}
if start.elapsed() > timeout {
return Ok(false);
}
}
}
fn check(&self, tx: &TxDatagram, rx: &mut RxDatagram) -> Vec<bool> {
tx.headers()
.zip(rx.iter())
.map(|(h, r)| h.msg_id == r.ack)
.collect()
}
}
impl<T: Transducer> Link<T> for Box<dyn Link<T>> {
fn open(&mut self, devices: &[Device<T>]) -> Result<(), AUTDInternalError> {
self.as_mut().open(devices)
}
fn close(&mut self) -> Result<(), AUTDInternalError> {
self.as_mut().close()
}
fn send(&mut self, tx: &TxDatagram) -> Result<bool, AUTDInternalError> {
self.as_mut().send(tx)
}
fn receive(&mut self, rx: &mut RxDatagram) -> Result<bool, AUTDInternalError> {
self.as_mut().receive(rx)
}
fn is_open(&self) -> bool {
self.as_ref().is_open()
}
fn timeout(&self) -> Duration {
self.as_ref().timeout()
}
fn update_geometry(&mut self, devices: &[Device<T>]) -> Result<(), AUTDInternalError> {
self.as_mut().update_geometry(devices)
}
fn send_receive(
&mut self,
tx: &TxDatagram,
rx: &mut RxDatagram,
timeout: Duration,
) -> Result<bool, AUTDInternalError> {
self.as_mut().send_receive(tx, rx, timeout)
}
fn wait_msg_processed(
&mut self,
tx: &TxDatagram,
rx: &mut RxDatagram,
timeout: Duration,
) -> Result<bool, AUTDInternalError> {
self.as_mut().wait_msg_processed(tx, rx, timeout)
}
fn check(&self, tx: &TxDatagram, rx: &mut RxDatagram) -> Vec<bool> {
self.as_ref().check(tx, rx)
}
}