1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Xtra is a tiny, fast, and safe actor system.

#![feature(
    generic_associated_types,
    weak_counts,
    specialization,
    type_alias_impl_trait,
    doc_cfg,
    doc_spotlight
)]

#![deny(missing_docs, unsafe_code)]

mod message_channel;
pub use message_channel::{MessageChannel, MessageChannelExt, WeakMessageChannel};

mod envelope;

mod address;
pub use address::{Address, AddressExt, Disconnected, WeakAddress};

mod context;
pub use context::Context;

mod manager;
pub use manager::ActorManager;

/// Commonly used types from `xtra`
pub mod prelude {
    pub use crate::address::{Address, AddressExt};
    pub use crate::message_channel::{MessageChannel, MessageChannelExt};
    pub use crate::{Actor, Context, Handler, Message, SyncHandler};
}

use futures::future::{self, Future, Ready};

/// A message that can be sent to an [`Actor`](trait.Actor.html) for processing. They are processed
/// one at a time. Only actors implementing the corresponding [`Handler<M>`](trait.Handler.html)
/// trait can be sent a given message.
pub trait Message: Send + 'static {
    /// The return type of the message. It will be returned when the [`Address::send`](struct.Address.html#method.send)
    /// method is called.
    type Result: Send;
}

/// A trait indicating that an [`Actor`](trait.Actor.html) can handle a given [`Message`](trait.Message.html)
/// synchronously, and the logic to handle the message. A `SyncHandler` implementation automatically
/// creates a corresponding [`Handler`](trait.Handler.html) impl. This, however, is not just sugar
/// over the asynchronous  [`Handler`](trait.Handler.html) trait -- it is also slightly faster than
/// it for handling due to how they get specialized under the hood.
pub trait SyncHandler<M: Message>: Actor {
    /// Handle a given message, returning its result.
    fn handle(&mut self, message: M, ctx: &mut Context<Self>) -> M::Result;
}

/// A trait indicating that an [`Actor`](trait.Actor.html) can handle a given [`Message`](trait.Message.html)
/// asynchronously, and the logic to handle the message. If the message should be handled synchronously,
/// then the [`SyncHandler`](trait.SyncHandler.html) trait should rather be implemented.
pub trait Handler<M: Message>: Actor {
    /// The responding future of the asynchronous actor. This should probably look like:
    /// ```ignore
    /// type Responder<'a>: Future<Output = M::Result> + Send
    /// ```
    type Responder<'a>: Future<Output = M::Result> + Send;

    /// Handle a given message, returning a future eventually resolving to its result. The signature
    /// of this function should probably look like:
    /// ```ignore
    /// fn handle(&mut self, message: M, ctx: &mut Context<Self>) -> Self::Responder<'_>
    /// ```
    /// or:
    /// ```ignore
    /// fn handle<'a>(&'a mut self, message: M, ctx: &'a mut Context<Self>) -> Self::Responder<'a>
    /// ```
    fn handle<'a>(&'a mut self, message: M, ctx: &'a mut Context<Self>) -> Self::Responder<'a>;
}

impl<M: Message, T: SyncHandler<M>> Handler<M> for T {
    type Responder<'a> = Ready<M::Result>;

    fn handle(&mut self, message: M, ctx: &mut Context<Self>) -> Self::Responder<'_> {
        let res: M::Result = SyncHandler::handle(self, message, ctx);
        future::ready(res)
    }
}

/// An actor which can handle [`Message`s](trait.Message.html) one at a time. Actors can only be
/// communicated with by sending [`Message`s](trait.Message.html) through their [`Address`es](struct.Address.html).
/// They can modify their private state, respond to messages, and spawn other actors. They can also
/// stop themselves through their [`Context`](struct.Context.html) by calling [`Context::stop`](struct.Context.html#method.stop).
/// This will result in any attempt to send messages to the actor in future failing.
pub trait Actor: 'static + Sized {
    /// Called as soon as the actor has been started.
    #[allow(unused_variables)]
    fn started(&mut self, ctx: &mut Context<Self>) {}

    /// Called when the actor calls the [`Context::stop`](struct.Context.html#method.stop). This method
    /// can prevent the actor from stopping by returning [`KeepRunning::Yes`](enum.KeepRunning.html#variant.Yes).
    ///
    /// **Note:** this method will *only* be called when `Context::stop` is called. Other, general
    /// destructor behaviour should be encapsulated in the [`Actor::stopped`](trait.Actor.html#method.stopped)
    /// method.
    #[allow(unused_variables)]
    fn stopping(&mut self, ctx: &mut Context<Self>) -> KeepRunning {
        KeepRunning::No
    }

    /// Called when the actor is in the process of stopping. This could be because
    /// [`KeepRunning::No`](enum.KeepRunning.html#variant.No) was returned from the
    /// [`Actor::stopping`](trait.Actor.html#method.stopping) method, or because there are no more
    /// strong addresses ([`Address`](struct.Address.html), as opposed to [`WeakAddress`](struct.WeakAddress.html).
    /// This should be used for any final cleanup before the actor is dropped.
    #[allow(unused_variables)]
    fn stopped(&mut self, ctx: &mut Context<Self>) {}

    /// Spawns the actor onto the global runtime executor (i.e, `tokio` or `async_std`'s executors).
    #[doc(cfg(feature = "with-tokio-0_2"))]
    #[doc(cfg(feature = "with-async_std-1"))]
    #[cfg(any(doc, feature = "with-tokio-0_2", feature = "with-async_std-1"))]
    fn spawn(self) -> Address<Self>
    where
        Self: Send,
    {
        ActorManager::spawn(self)
    }

    /// Returns the actor's address and manager in a ready-to-start state. To spawn the actor, the
    /// [`ActorManager::manage`](struct.ActorManager.html#method.manage) method must be called and
    /// the future it returns spawned onto an executor.
    fn create(self) -> (Address<Self>, ActorManager<Self>) {
        ActorManager::start(self)
    }
}

/// Whether to keep the actor running after it has been put into a stopping state.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum KeepRunning {
    /// Keep the actor running and prevent it from being stopped
    Yes,
    /// Stop the actor
    No,
}