pub trait Actor: 'static + Send + Sized {
fn started<'life0, 'life1, 'async_trait>(
&'life0 mut self,
ctx: &'life1 mut Context<Self>
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
{ ... }
fn stopping<'life0, 'life1, 'async_trait>(
&'life0 mut self,
ctx: &'life1 mut Context<Self>
) -> Pin<Box<dyn Future<Output = KeepRunning> + Send + 'async_trait>>
where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
{ ... }
fn stopped<'life0, 'async_trait>(
&'life0 mut self
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where
'life0: 'async_trait,
Self: 'async_trait,
{ ... }
fn create(self, message_cap: Option<usize>) -> ActorManager<Self> { ... }
}
Expand description
An actor which can handle Message
s one at a time. Actors can only be
communicated with by sending Message
s through their Address
es.
They can modify their private state, respond to messages, and spawn other actors. They can also
stop themselves through their Context
by calling Context::stop
.
This will result in any attempt to send messages to the actor in future failing.
This is an async_trait
, so implementations should
be annotated #[async_trait]
.
Example
struct MyActor;
#[async_trait::async_trait]
impl Actor for MyActor {
async fn started(&mut self, ctx: &mut Context<Self>) {
println!("Started!");
}
async fn stopping(&mut self, ctx: &mut Context<Self>) -> KeepRunning {
println!("Decided not to keep running");
KeepRunning::StopAll
}
async fn stopped(&mut self) {
println!("Finally stopping.");
}
}
struct Goodbye;
impl Message for Goodbye {
type Result = ();
}
#[async_trait::async_trait]
impl Handler<Goodbye> for MyActor {
async fn handle(&mut self, _: Goodbye, ctx: &mut Context<Self>) {
println!("Goodbye!");
ctx.stop();
}
}
// Will print "Started!", "Goodbye!", "Decided not to keep running", and then "Finally stopping."
smol::block_on(async {
let addr = MyActor.create(None).spawn(&mut Smol::Global);
addr.send(Goodbye).await;
Timer::after(Duration::from_secs(1)).await; // Give it time to run
})
For longer examples, see the examples
directory.
Provided Methods
Called as soon as the actor has been started.
Called when the actor calls the Context::stop
. This method
can prevent the actor from stopping by returning KeepRunning::Yes
.
If this method returns KeepRunning::StopSelf
,
this actor will be stopped. If it returns
KeepRunning::StopAll
, then all actors on the same
address as this actor will be stopped. This can take a little bit of time to propagate.
Note: this method will only be called when Context::stop
is called from this actor. If the last strong address to the actor is dropped, or
Context::stop
is called from another actor on the same
address, this will not be called. Therefore, Other, general destructor behaviour should be
encapsulated in the Actor::stopped
method.
Example
async fn stopping(&mut self, ctx: &mut Context<Self>) -> KeepRunning {
self.is_running.into() // bool can be converted to KeepRunning with Into
}
Called when the actor is in the process of stopping. This could be because
KeepRunning::StopAll
or
KeepRunning::StopSelf
was returned from the
Actor::stopping
method, or because there are no more
strong addresses (Address
, as opposed to
WeakAddress
. This should be used for any final cleanup before
the actor is dropped.
fn create(self, message_cap: Option<usize>) -> ActorManager<Self>
fn create(self, message_cap: Option<usize>) -> ActorManager<Self>
Returns the actor’s address and manager in a ready-to-start state, given the cap for the
actor’s mailbox. If None
is passed, it will be of unbounded size. To spawn the actor,
the ActorManager::spawn
must be called, or
the ActorManager::run
method must be called
and the future it returns spawned onto an executor.
Example
smol::block_on(async {
let (addr, fut) = MyActor.create(None).run();
smol::spawn(fut).detach(); // Actually spawn the actor onto an executor
Timer::after(Duration::from_secs(1)).await; // Give it time to run
})