#worker-thread #run-time #actor #function #async

nightly heph-rt

Heph-rt是Heph的actor的专用运行时。

2个版本

0.4.1 2022年10月14日
0.4.0 2022年4月21日

#39 in #worker-thread

MIT许可证

740KB
13K SLoC

Heph-rt

License: MIT Crates.io Docs

Heph actor的专用运行时。

有关更多信息,请参阅主Heph README


lib.rs:

Heph actor的专用运行时。

如果您是第一次接触Heph,最好先从Heph crate开始。

crate的根目录有两个主要类型

  • Runtime是Heph的运行时,用于运行所有actor。
  • RuntimeRef是运行时引用,用于例如启动新的actor。

运行Heph的运行时

构建运行时从调用setup开始,这将创建一个新的Setup构建器类型,允许配置Runtime。也可以使用new函数,但主要仅用于快速原型设计或测试。

Setup有几个配置选项。其中一个选项示例是运行时使用的线程数,这可以通过num_threadsuse_all_cores方法进行配置。当使用use_all_cores时,可以使用auto_cpu_affinity自动设置CPU亲和性。

一旦运行时完全配置,就可以通过build构建它,这将返回Runtime类型。

在运行时构建完成后,也可以使用在 Runtime 上的 Spawn 实现,或使用 try_spawn 来启动线程安全的演员。可以使用 spawn_sync_actor 来启动同步演员。然而,请注意,大多数演员应该作为线程-局部演员运行。要启动线程局部演员,请参阅 Spawn 实现,用于 RuntimeRefRuntimeRef::try_spawn_local,它可以选择启动线程安全和线程局部演员。有关不同类型演员的文档,请参阅 actor 模块。

为了帮助初始化和启动线程局部演员,可以使用 run_on_workers 在所有工作线程上运行函数。这将运行相同的(克隆的)函数在所有工作线程上,并且可以访问 RuntimeRef

最后,在配置运行时和启动演员后,可以启动运行时 start,它将运行所有演员并等待它们完成。

示例

这个简单的示例展示了如何运行一个 Runtime 并在每个线程上启动单个演员。这应该打印 "Hello World" 两次(每个启动的工作线程一次)。

#![feature(never_type)]

use heph::actor;
use heph::supervisor::NoSupervisor;
use heph_rt::spawn::ActorOptions;
use heph_rt::{self as rt, Runtime, RuntimeRef, ThreadLocal};

fn main() -> Result<(), rt::Error> {
    // Build a new `Runtime` with two worker threads.
    let mut runtime = Runtime::setup().num_threads(2).build()?;
    // On each worker thread run our setup function.
    runtime.run_on_workers(setup)?;
    // And start the runtime.
    runtime.start()
}

// This setup function will on run on each created thread. In the case of
// this example we create two threads (see `main`).
fn setup(mut runtime_ref: RuntimeRef) -> Result<(), !> {
    // Asynchronous function don't yet implement the required `NewActor`
    // trait, but function pointers do so we cast our type to a function
    // pointer.
    let actor = actor as fn(_, _) -> _;
    // Each actors needs to be supervised, but since our actor doesn't
    // return an error (the error type is `!`) we can get away with our
    // `NoSupervisor` which doesn't do anything (as it can never be called).
    let supervisor = NoSupervisor;
    // All actors start with one or more arguments, in our case it's message
    // used to greet people with. See `actor` below.
    let arg = "Hello";
    // Spawn the actor to run on our actor runtime. We get an actor reference
    // back which can be used to send the actor messages, see below.
    let actor_ref = runtime_ref.spawn_local(supervisor, actor, arg, ActorOptions::default());

    // Send a message to the actor we just spawned.
    actor_ref.try_send("World").unwrap();

    Ok(())
}

/// Our actor that greets people.
async fn actor(mut ctx: actor::Context<&'static str, ThreadLocal>, msg: &'static str) {
    // `msg` is the argument passed to `spawn` in the `setup` function
    // above, in this example it was "Hello".

    // Using the context we can receive messages send to this actor, so here
    // we'll receive the "World" message we send in the `setup` function.
    if let Ok(name) = ctx.receive_next().await {
        // This should print "Hello world"!
        println!("{} {}", msg, name);
    }
}

有关更多示例,请参阅源代码中的 examples 目录

特性

此软件包有一个可选的:test。`test` 特性将启用 `test` 模块,该模块添加了测试功能。

依赖关系

~1–11MB
~69K SLoC