#actor #xtra #async-await #future #async #impl-block

spaad_internal

spaad 包提供的 proc-macro。不要直接使用它,而是使用它。

7 个版本

0.4.1 2023年2月15日
0.4.0 2021年10月6日
0.4.0-beta.12020年7月5日
0.3.2 2020年6月19日
0.2.0 2020年6月9日

#8 in #xtra

49 每月下载量
用于 spaad

MPL-2.0 许可证

36KB
777

spaad

Spooky action at a distance

spaad 是一个去除大多数 xtra 模板代码的包,xtra 是一个微型的 actor 框架。它通过 proc-macro:spaad::entangled 来实现这一点。结果是,编写消息处理程序和调用它看起来几乎与传统的函数调用相同。

例如,一个处理程序看起来像这样

#[spaad::entangled]
impl MyActor {
    async fn print(&mut self) { /* ... */ }
}

并且像这样调用

my_actor.print().await;

用法

proc-macro spaad::entangled 是 spaad 的核心元素。它从其签名创建每个处理程序的消息和 Handler 实现,以及一个包装地址的结构体,它具有发送消息的易于使用的函数名。最终结果是,调用者和被调用者看起来好像没有actor的参与。包的名称是一个俏皮的引用,即爱因斯坦所说的量子纠缠——“spooky action at a distance”——因为在这种情况下,一个粒子的状态似乎也“神奇”地改变了。

这个宏用作 actor 结构定义和其实例块上的属性。

示例

use xtra::prelude::*;

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

#[spaad::entangled]
impl Actor for Printer {}

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

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

#[tokio::main]
async fn main() {
    // a Spawner must be provided as the last argument here
    let printer = Printer::new(&mut xtra::spawner::Tokio::Global);

    loop {
        printer.print("hello".to_string()).await;
    }
}

生成的 Printer 类型实际上并不包含结构体的所有成员,而是包含其地址。实际的结构体是严格内部的,不能通过发送消息或在其 impl 块内部与其交互。当在 impl 块内部作为类型引用时,必须使用 Self,因为它将被重命名。

请注意,new函数是一个特例。如果存在,proc宏将为actor包装器生成一个create方法,对应于Actor::create。它可以接受参数。如果启用了with-tokio-0_2with-async_std-1_0功能,则还会生成一个new方法,对应于Actor::spawn

如果您不想等待消息完成处理,可以执行以下操作

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

对于更复杂的示例,例如处理actor的断开连接以及在处理程序中获取Context,请参阅文档或示例目录中的complex.rs。要查看生成的代码,请在example_generated文件夹中运行cargo +nightly doc

优点

  • 更方便、更简洁。
  • IDE支持。在某些IDE中(仅在安装了Rust插件的IntelliJ IDEA上进行了测试),可以跳转到定义。这是部分支持,因为在某些情况下,IDE不理解self参数的可变性变化(在发送消息时只需要&self,但它看起来像被声明为&mut self)。
  • 可以使用nightly API,同时降低UB(通过在GAT中减少UB的机会),并且完全透明。

缺点

  • 与xtra本身类似的注意事项:不成熟。
  • IDE支持并不完整。在某些情况下,可能会出现问题。这可以通过proc宏展开来解决,但似乎还有很长的路要走。Rust Analyzer似乎比IntelliJ Rust更好地处理这个问题,尽管这可能会改变。

Nightly API

为了启用xtra的nightly API,请在您的Cargo.toml中禁用默认的stable功能。

版本兼容性

Spaad 0.4.0与xtra 0.5.0兼容。

依赖关系

~0.3–0.8MB
~19K SLoC