xtra 0.5.2

A tiny actor framework
Documentation
use std::future::Future;

use crate::address::Address;
use crate::context::Context;
use crate::envelope::{BroadcastMessageEnvelope, MessageEnvelope};
use crate::spawn::Spawner;
use crate::Actor;

/// A message that can be sent by an Address to the manage loop
pub(crate) enum AddressMessage<A: Actor> {
    /// A message from the last address telling the actor that it should shut down
    LastAddress,
    /// A message being sent to the actor. To read about envelopes and why we use them, check out
    /// `envelope.rs`
    Message(Box<dyn MessageEnvelope<Actor = A>>),
}

/// A message that can be sent by another actor on the same address to the manage loop
pub(crate) enum BroadcastMessage<A: Actor> {
    /// A message from another actor on the same address telling the actor to unconditionally shut
    /// down.
    Shutdown,
    Message(Box<dyn BroadcastMessageEnvelope<Actor = A>>),
}

impl<A: Actor> Clone for BroadcastMessage<A> {
    fn clone(&self) -> Self {
        use self::BroadcastMessage::*;
        match self {
            Shutdown => Shutdown,
            Message(msg) => Message(msg.clone()),
        }
    }
}

/// If and how to continue the manage loop
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub(crate) enum ContinueManageLoop {
    Yes,
    ExitImmediately,
}

/// A manager for the actor which handles incoming messages and stores the context. Its managing
/// loop can be started with [`ActorManager::run`](struct.ActorManager.html#method.run).
pub struct ActorManager<A: Actor> {
    pub(crate) address: Address<A>,
    pub(crate) actor: A,
    pub(crate) ctx: Context<A>,
}

impl<A: Actor> ActorManager<A> {
    /// Spawn the actor's main loop on the given runtime. This will allow it to handle messages.
    pub fn spawn<S: Spawner>(self, spawner: &mut S) -> Address<A> {
        let (addr, fut) = self.run();
        spawner.spawn(fut);
        addr
    }

    /// Starts the manager loop, returning the actor's address and its manage future. This will
    /// start the actor and allow it to respond to messages.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use xtra::prelude::*;
    /// struct MyActor;
    /// impl Actor for MyActor {}
    ///
    /// smol::block_on(async {
    ///     let (addr, fut) = MyActor.create(None).run();
    ///     smol::spawn(fut).detach(); // Actually spawn the actor onto an executor
    /// });
    /// ```
    pub fn run(self) -> (Address<A>, impl Future<Output = ()>) {
        (self.address, self.ctx.run(self.actor))
    }
}