#[act_zero]Expand description
§The #[act_zero] macro.
This macro is used in two locations, which will be documented separately:
§Trait position
#[act_zero]
trait Greeter {
fn greet(&self, name: String, res: Sender<String>);
}This is used to define an actor trait. Actor traits (much like normal traits) define a set of methods to be implemented by the actor type. However, there are a number of constraints:
- Methods must take
&selfas the receiver. - All argument types must be
Send + 'static. - Generic methods must have a
where Self: Sizedbound. - There must be no return type.
- If the last argument is named
res, it must be of typeSender<_>.
These last two constraints are related: actor systems work by passing messages and
processing them asynchronously. Any return value would not be immediately available,
so instead the caller passes in a Sender<_> to receive the result.
As a convenience, there will be an asynchronous call_xyz() method to hide this
complexity from the caller:
let addr: Addr<dyn Greeter> = ...;
let res = addr.call_greet("John".into()).await?;Internally, this macro defines several additional items:
trait GreeterImplYou will never use this trait directly, but if you want your trait to be implementable by downstream crates, you must export this trait under the same path as the actor trait itself.enum GreeterMsgThis enum contains a variant for each object-safe method in the trait. It is used in remoting scenarios when messages may need to be trasferred between processes or over the network, but is otherwise not used.trait GreeterExtThis trait is implemented for theAddrandWeakAddrtypes when they contain a type implementing the actor trait. Methods on this trait are the primary way you would interact with the actor, and this is where helper methods likecall_greeterare defined.
§Trait implementation position
#[act_zero]
impl Greeter for SimpleGreeter {
async fn greet(&mut self, name: String, res: Sender<String>) {
self.number_of_greets += 1;
res.send(format!(
"Hello, {}. You are number {}!",
name, self.number_of_greets
))
.ok();
}
}This is used to implement an actor trait for an actor. The signature of the methods in the implementation differ substantially from those signature in the trait definition:
-
All methods must be
async. This may be optional in future. -
Methods can return any type implementing
IntoResult. If an error variant is returned it will be passed to the appropriate error handler implemented for the actor. -
The receiver type can be any of:
-
&mut selfThe method will run to completion with exclusive access to the actor state. No methods taking&selfor&mut selfcan run concurrently. Long running methods taking&mut selfshould be avoided if you want your actor to stay responsive to new messages. -
&selfThe method will run to completion with shared access to the actor state. Other methods taking&selfcan run concurrently, but methods taking&mut selfcannot. -
self: Addr<Local<Self>>The method has no direct access to the actor state, but can run concurrently with any other methods, including those taking&mut self. This can be useful for implementing delayed or timed events without blocking the actor. Access to the actor state can be achieved by awaiting another method on the actor to do the update.
-
No additional items are generated by the expansion of this variant of the macro.