2个版本
0.4.1 | 2022年10月14日 |
---|---|
0.4.0 | 2022年4月21日 |
#39 in #worker-thread
740KB
13K SLoC
Heph-rt
Heph actor的专用运行时。
有关更多信息,请参阅主Heph README。
lib.rs
:
Heph actor的专用运行时。
如果您是第一次接触Heph,最好先从Heph crate开始。
crate的根目录有两个主要类型
Runtime
是Heph的运行时,用于运行所有actor。RuntimeRef
是运行时引用,用于例如启动新的actor。
运行Heph的运行时
构建运行时从调用setup
开始,这将创建一个新的Setup
构建器类型,允许配置Runtime
。也可以使用new
函数,但主要仅用于快速原型设计或测试。
Setup
有几个配置选项。其中一个选项示例是运行时使用的线程数,这可以通过num_threads
和use_all_cores
方法进行配置。当使用use_all_cores
时,可以使用auto_cpu_affinity
自动设置CPU亲和性。
一旦运行时完全配置,就可以通过build
构建它,这将返回Runtime
类型。
在运行时构建完成后,也可以使用在 Runtime
上的 Spawn
实现,或使用 try_spawn
来启动线程安全的演员。可以使用 spawn_sync_actor
来启动同步演员。然而,请注意,大多数演员应该作为线程-局部演员运行。要启动线程局部演员,请参阅 Spawn
实现,用于 RuntimeRef
或 RuntimeRef::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