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, }