extern crate failure;
use failure::Error;
use std::marker::PhantomData;
use std::sync::{Arc, Weak, Mutex, MutexGuard};
use std::thread;
pub trait Emitter: Send {
type input;
fn emit(&mut self, Self::input);
}
#[derive(Clone)]
pub struct Am<T: Sized>(Arc<Mutex<T>>);
pub type Wm<T> = Weak<Mutex<T>>;
pub type AmEmitter<T> = Am<Emitter<input=T>>;
type WmEmitter<T> = Wm<Emitter<input=T>>;
impl<T: Sized> Am<T> {
pub fn new(data: T) -> Self {
Am(Arc::new(Mutex::new(data)))
}
pub fn lock(&self) -> MutexGuard<'_, T> {
self.0.lock().unwrap()
}
pub fn clone(&self) -> Self {
Am(self.0.clone())
}
}
pub trait SigFn<I, O>: Fn(I) -> Result<O, Error> {}
impl<F, I, O> SigFn<I, O> for F where F: Fn(I) -> Result<O, Error> {}
impl<I,O,F> Emitter for Signal<I,O,F>
where F: 'static + SigFn<I, O> + Send + Sync,
O: 'static + PartialEq + Send + Sync + Clone,
I: 'static + Send + Sync
{
type input = I;
fn emit(&mut self, data: Self::input) {
let output = (self.func)(data);
match output {
Ok(output) => {
if let Some(ref out) = self.output {
if *out == output {
return;
}
}
self.output = Some(output);
self.emit_children();
},
Err(e) => println!("Error: {:?}", e),
};
}
}
pub struct Signal<I, O, F>
where F: SigFn<I, O>
{
input: PhantomData<I>,
output: Option<O>,
func: F,
listeners: Vec< WmEmitter<O> >,
threaded_listeners: Vec< WmEmitter<O> >,
}
impl<I,O,F> Signal<I,O,F>
where F: 'static + SigFn<I, O> + Send + Sync,
O: 'static + Send + Sync + Clone,
I: 'static + Send + Sync,
{
fn new_signal(f: F) -> Signal<I, O, impl SigFn<I, O>> {
Signal {
input: PhantomData,
output: None,
func: move |i: _| f(i),
listeners: Vec::new(),
threaded_listeners: Vec::new(),
}
}
pub fn new_arc_mutex(f: F) -> Am<Signal<I, O, impl SigFn<I, O>>> {
Am::new(Signal::new_signal(f))
}
fn emit_children(&mut self) {
for signal in self.listeners.iter() {
let output = self.output.clone();
Self::emit_child(signal.clone(), output);
}
for signal in self.threaded_listeners.iter() {
let signal = signal.clone();
let output = self.output.clone();
thread::spawn( move || Self::emit_child(signal, output) );
}
}
fn emit_child(signal: WmEmitter<O>, output: Option<O>) {
if let Some(signal) = signal.upgrade() {
if let Some(ref output) = output {
let output = output.clone();
if let Ok(mut signal) = signal.lock() {
signal.emit(output);
}
}
}
}
pub fn create_listener<Q, G>(&mut self, f: G) -> Am<Signal<O, Q, impl SigFn<O,Q>>>
where G: 'static + SigFn<O,Q> + Send + Sync,
Q: 'static + PartialEq + Send + Sync + Clone,
O: 'static
{
let ret = Signal::new_arc_mutex(f);
self.register_listener(&ret);
ret
}
pub fn create_threaded_listener<Q, G>(&mut self, f: G) -> Am<Signal<O, Q, impl SigFn<O,Q>>>
where G: 'static + SigFn<O,Q> + Send + Sync,
Q: 'static + PartialEq + Send + Sync + Clone,
O: 'static
{
let ret = Signal::new_arc_mutex(f);
self.register_threaded_listener(&ret);
ret
}
pub fn register_listener<E>(&mut self, strong: &Am<E>)
where E: 'static + Emitter<input=O>
{
let weak = Arc::downgrade(&strong.0);
self.listeners.push(weak);
}
pub fn register_threaded_listener<E>(&mut self, strong: &Am<E>)
where E: 'static + Emitter<input=O>
{
let weak = Arc::downgrade(&strong.0);
self.threaded_listeners.push(weak);
}
pub fn get(&self) -> &Option<O> { &self.output }
}