[][src]Attribute Macro spaad::entangled

#[entangled]

The main item of the crate. This is a proc macro used as an attribute on the actor struct definition, Actor implementation, and on an impl block in which the handler functions are used.

Example

This example is not tested
#![feature(type_alias_impl_trait, generic_associated_types)]

#[spaad::entangled]
struct Printer {
    times: usize,
}

#[spaad::entangled]
impl Actor for Printer {
    fn started(&mut self, _ctx: &mut Context<Self>) {
        println!("Actor started!");
    }
}

#[spaad::entangled]
impl Printer {
    #[spaad::spawn]
    fn new() -> Printer {
        Printer { times: 0 }
    }

    #[spaad::handler]
    async fn print(&mut self, string: String) {
        self.times += 1;
        println!("Printing {}. Printed {} times so far.", string, self.times);
    }
}

Constructors

To emit a constructor for an actor, the #[spaad::spawn] or #[spaad::create] attributes can be used. The spawn macro will emit a method that constructs the actor with the given arguments and spawns it onto whichever runtime spaad is set to use (currently, tokio, async_std, or wasm-bindgen at your option). It is analagous to Actor::spawn. Similarly, create will construct the actor, and return the address of the actor and its manager, ready to be spawned onto any runtime. You can even have both on one function with rename:

This example is not tested
#[spaad::spawn]
#[spaad::create(rename = "create")]
fn new(x: u32) -> MyActor {
    MyActor { x }
}

This will cause a create function to be emitted, as well as a a spawn function named new.

Sending Messages

Messages can then be sent to actors as such:

This example is not tested
my_actor.print().await;

The output type of the future will be determined by the signature. It will be identical to the written type, except when the return is written as Result<T, xtra::Disconnected> (see below).

If you do not want to await for the message to complete processing, you can do the following:

This example is not tested
let _ = my_actor.print(); // Binding to avoid #[must_use] warning on Future

This will also mean that the return type will be discarded, as the receiving end of the channel will be dropped.

Handling disconnection

The methods to send messages will panic if the actor is disconnected. If you want to manually handle this error, make the return type of the handler function Result<T, xtra::Disconnected>. The type must be named Context - it cannot be renamed by re-importing. If you want to access the actor cotnext add an argument to the function with &mut Context<Self> as the type. Similarly, the type must be named Context - it cannot be renamed by re-importing.

Implementations in other modules

To implement something on an actor in a module other than where it is declared, you will need to refer to it either by its fully-qualified path (e.g crate::actor::MyActor) or a local path (e.g super::MyActor) when writing the self-type. So, instead of writing this:

This example is not tested
use super::MyActor;
#[spaad::entangled]
impl AsRef<i32> for MyActor { /* ... */ }

you must write this:

This example is not tested
#[spaad::entangled]
impl AsRef<i32> for super::MyActor { /* ... */ }

This is a limitation due to how the macro expands, and should be resolved when there is support for inherent-impl type aliases (see rust/60471). This is currently blocked on lazy normalization.