use super::*;
pub trait DynamicComponentDefinition:
DynamicPortAccess + ActorRaw + ComponentLifecycle + Send
{
}
impl<T> DynamicComponentDefinition for T where
T: DynamicPortAccess + ActorRaw + ComponentLifecycle + Send
{
}
pub trait ComponentDefinition: DynamicComponentDefinition
where
Self: Sized + 'static,
{
fn setup(&mut self, self_component: Arc<Component<Self>>) -> ();
fn execute(&mut self, max_events: usize, skip: usize) -> ExecuteResult;
fn ctx(&self) -> &ComponentContext<Self>;
fn ctx_mut(&mut self) -> &mut ComponentContext<Self>;
fn type_name() -> &'static str;
fn spawn_local<F>(&mut self, f: impl FnOnce(ComponentDefinitionAccess<Self>) -> F)
where
Self: 'static,
F: futures::Future<Output = Handled> + Send + 'static,
{
let future = future_task::non_blocking(self, f);
future.schedule();
let tag = future.tag();
self.ctx_mut().non_blocking_futures.insert(tag, future);
}
fn spawn_off<R: Send + 'static>(
&self,
future: impl futures::Future<Output = R> + 'static + Send,
) -> JoinHandle<R> {
self.ctx().system().spawn(future)
}
}
pub trait ComponentLifecycle: ComponentLogging {
fn on_start(&mut self) -> Handled
where
Self: 'static,
{
debug!(self.log(), "Starting...");
Handled::Ok
}
fn on_stop(&mut self) -> Handled
where
Self: 'static,
{
debug!(self.log(), "Stopping...");
Handled::Ok
}
fn on_kill(&mut self) -> Handled
where
Self: 'static,
{
debug!(self.log(), "Killing...");
Handled::Ok
}
}
pub trait DynamicPortAccess {
fn get_provided_port_as_any(&mut self, port_id: std::any::TypeId) -> Option<&mut dyn Any>;
fn get_required_port_as_any(&mut self, port_id: std::any::TypeId) -> Option<&mut dyn Any>;
}
impl<M: MessageBounds> dyn DynamicComponentDefinition<Message = M> + '_ {
pub fn get_provided_port<P: Port>(&mut self) -> Option<&mut ProvidedPort<P>> {
self.get_provided_port_as_any(std::any::TypeId::of::<P>())
.and_then(|any| any.downcast_mut())
}
pub fn get_required_port<P: Port>(&mut self) -> Option<&mut RequiredPort<P>> {
self.get_required_port_as_any(std::any::TypeId::of::<P>())
.and_then(|any| any.downcast_mut())
}
}
pub type DynamicComponentDefinitionMutexGuard<'a, M> =
OwningRefMut<Box<dyn Erased + 'a>, dyn DynamicComponentDefinition<Message = M>>;
#[derive(Debug)]
pub struct LockPoisoned;
impl fmt::Display for LockPoisoned {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "component definition lock has been poisoned")
}
}
impl std::error::Error for LockPoisoned {}
pub trait AbstractComponent: MsgQueueContainer + CoreContainer + Any {
fn dyn_definition_mut(
&mut self,
) -> &mut dyn DynamicComponentDefinition<Message = Self::Message>;
fn lock_dyn_definition(
&self,
) -> Result<DynamicComponentDefinitionMutexGuard<Self::Message>, LockPoisoned>;
fn as_any(&self) -> &dyn Any;
fn as_queue_container(self: Arc<Self>) -> Weak<dyn MsgQueueContainer<Message = Self::Message>>;
}
impl<C> AbstractComponent for Component<C>
where
C: ComponentTraits + ComponentLifecycle,
{
fn dyn_definition_mut(
&mut self,
) -> &mut dyn DynamicComponentDefinition<Message = Self::Message> {
self.definition_mut()
}
fn lock_dyn_definition(
&self,
) -> Result<DynamicComponentDefinitionMutexGuard<Self::Message>, LockPoisoned> {
let lock = self.mutable_core.lock().map_err(|_| LockPoisoned)?;
let res = OwningRefMut::new(Box::new(lock))
.map_mut(|l| {
(&mut l.deref_mut().definition)
as &mut dyn DynamicComponentDefinition<Message = Self::Message>
})
.erase_owner();
Ok(res)
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_queue_container(self: Arc<Self>) -> Weak<dyn MsgQueueContainer<Message = Self::Message>> {
let res: Weak<Self> = Arc::downgrade(&self);
res as Weak<dyn MsgQueueContainer<Message = Self::Message>>
}
}
impl<M: MessageBounds> dyn AbstractComponent<Message = M> {
pub fn on_dyn_definition<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut dyn DynamicComponentDefinition<Message = M>) -> R,
{
let mut lock = self.lock_dyn_definition().unwrap();
f(&mut *lock)
}
}