use core::any::Any;
use alloc::sync::Arc;
pub trait Actor: Send + Sync + 'static {
#[cfg(feature = "async")]
fn destroy(&self) -> impl core::future::Future<Output = ()> + Send {
async {}
}
#[cfg(not(feature = "async"))]
fn destroy(&self) {}
}
pub trait Handler<T: Message>: Actor {
#[cfg(feature = "async")]
fn handle_message(&self, message: T) -> impl core::future::Future<Output = T::Result> + Send;
#[cfg(not(feature = "async"))]
fn handle_message(&self, message: T) -> T::Result;
}
pub trait Message: Send + Sync + 'static {
type Result: Send + Sync + 'static;
}
pub trait MessageSender<M: Message> {
#[cfg(feature = "async")]
fn send(&self, message: M) -> impl core::future::Future<Output = M::Result> + Send;
#[cfg(not(feature = "async"))]
fn send(&self, message: M) -> M::Result;
}
#[repr(transparent)]
pub struct ActorHandle<A: Actor>(Arc<A>);
impl<A: Actor> ActorHandle<A> {
pub(crate) fn new(actor: A) -> Self {
Self(Arc::new(actor))
}
#[cfg(feature = "async")]
pub async fn send<M: Message>(&self, message: M) -> M::Result
where A: Handler<M> {
self.0.handle_message(message).await
}
#[cfg(not(feature = "async"))]
pub fn send<M: Message>(&self, message: M) -> M::Result
where A: Handler<M> {
self.0.handle_message(message)
}
#[cfg(feature = "async")]
pub async fn kill(&self) {
self.0.destroy().await;
}
#[cfg(not(feature = "async"))]
pub fn kill(&self) {
self.0.destroy();
}
}
impl<M: Message, A: Actor + Handler<M>> MessageSender<M> for ActorHandle<A> {
#[cfg(feature = "async")]
async fn send(&self, message: M) -> M::Result {
self.0.handle_message(message).await
}
#[cfg(not(feature = "async"))]
fn send(&self, message: M) -> M::Result {
self.0.handle_message(message)
}
}
impl<A: Actor> ActorRef for ActorHandle<A> {
#[inline(always)]
fn as_any(&self) -> &dyn Any {
self
}
#[cfg(not(feature = "async"))]
fn kill(&self) {
self.0.destroy();
}
#[cfg(feature = "async")]
fn kill(&self) -> core::pin::Pin<alloc::boxed::Box<dyn core::future::Future<Output = ()> + Send + '_>> {
alloc::boxed::Box::pin(async {
self.0.destroy().await
})
}
}
impl<A: Actor> Clone for ActorHandle<A> {
#[inline(always)]
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
pub(crate) trait ActorRef: Send + Sync + 'static {
fn as_any(&self) -> &dyn Any;
#[cfg(not(feature = "async"))]
fn kill(&self);
#[cfg(feature = "async")]
fn kill(&self) -> core::pin::Pin<alloc::boxed::Box<dyn core::future::Future<Output = ()> + Send + '_>>;
}