#[macro_use]
extern crate secop_core;
mod simcryo;
mod serial;
mod tcp;
mod toellner;
pub(crate) mod support;
use std::panic::catch_unwind;
use std::error::Error as StdError;
use std::time::Duration;
use std::thread::{Builder, sleep};
use log::*;
use secop_core::module::{Module, ModInternals};
fn inner_run<T: Module>(internals: ModInternals) {
let name = internals.name().to_owned();
Builder::new().name(name.clone()).spawn(move || loop {
if catch_unwind(|| {
T::create(internals.clone()).expect("init failed").run()
}).is_err() {
error!("module {} panicked, waiting...", name);
internals.req_receiver().try_iter().count();
while internals.req_receiver().is_empty() {
sleep(Duration::from_millis(100));
}
info!("now restarting module {}", name);
}
}).expect("could not start thread");
}
pub fn run_module(internals: ModInternals) -> Result<(), Box<dyn StdError>> {
Ok(match &*internals.class() {
"SimCryo" => inner_run::<simcryo::SimCryo>(internals),
"SerialComm" => inner_run::<serial::SerialComm>(internals),
"TcpComm" => inner_run::<tcp::TcpComm>(internals),
"ToellnerPS" => inner_run::<toellner::ToellnerPS>(internals),
_ => return Err(format!("no such module class: {}", internals.class()).into())
})
}