radiate-engines 1.3.1

Engines for the Radiate genetic algorithm library.
Documentation
use crate::events::{EventStream, Subscription, SubscriptionId};
use radiate_core::{Executor, error::RadiateResult};
use std::sync::{Arc, Mutex};

pub trait Event: Send + Sync + 'static {}
impl<T: Send + Sync + 'static> Event for T {}

pub trait Handler<E: Event>: Send + 'static {
    fn handle(&mut self, event: &E, ctx: &EventContext<'_, Self>)
    where
        Self: Sized;
}

pub trait EventHandler: Send + 'static {
    fn start(&mut self, _ctx: &EventContext<'_, Self>) -> RadiateResult<()>
    where
        Self: Sized,
    {
        Ok(())
    }
}

impl<E, F> Handler<E> for F
where
    E: Event,
    F: FnMut(&E) + Send + 'static,
{
    fn handle(&mut self, event: &E, _ctx: &EventContext<'_, Self>) {
        self(event)
    }
}

pub struct EventContext<'a, H>(&'a Subscriber<H>);

impl<H> EventContext<'_, H> {
    pub fn publish<E: Event>(&self, event: E) {
        self.0.stream.publish(event);
    }

    pub fn subscribe<E>(&self) -> Subscription
    where
        E: Event,
        H: Handler<E>,
    {
        self.0.subscribe::<E>()
    }
}

pub struct Subscriber<H> {
    handler: Arc<Mutex<H>>,
    executor: Arc<Executor>,
    stream: EventStream,
}

impl<H: Send + 'static> Subscriber<H> {
    pub(super) fn new(handler: H, executor: Arc<Executor>, stream: EventStream) -> Self {
        Subscriber {
            handler: Arc::new(Mutex::new(handler)),
            executor,
            stream,
        }
    }

    pub fn subscribe<E>(&self) -> Subscription
    where
        E: Event,
        H: Handler<E>,
    {
        self.stream.subscribe_existing::<E, H>(self)
    }

    pub fn unsubscribe(&self, id: SubscriptionId) {
        self.stream.unsubscribe(id);
    }

    pub(super) fn start(&self) -> RadiateResult<()>
    where
        H: EventHandler,
    {
        let ctx = EventContext(self);
        self.handler.lock().unwrap().start(&ctx)
    }

    pub(super) fn send_shared<E>(&self, event: Arc<E>)
    where
        E: Event,
        H: Handler<E>,
    {
        match self.executor.as_ref() {
            Executor::Serial => {
                let ctx = EventContext(self);
                self.handler.lock().unwrap().handle(event.as_ref(), &ctx);
            }
            _ => {
                let owned = self.clone();
                self.executor.submit(move || {
                    let ctx = EventContext(&owned);
                    owned.handler.lock().unwrap().handle(event.as_ref(), &ctx);
                });
            }
        }
    }
}

impl<H> Clone for Subscriber<H> {
    fn clone(&self) -> Self {
        Subscriber {
            handler: Arc::clone(&self.handler),
            executor: Arc::clone(&self.executor),
            stream: self.stream.clone(),
        }
    }
}