#future #run-time #async #worker-thread #async-await

已弃用 naja_async_runtime

轻量级通用运行时,用于 futures

16 个版本

0.5.0-deprecated.12020 年 12 月 8 日
0.3.4 2019 年 10 月 11 日
0.3.0 2019 年 8 月 2 日
0.2.1 2019 年 7 月 19 日
0.1.7 2019 年 7 月 11 日

#51#worker-thread

每月 47 次下载

Unlicense 许可

60KB
752 代码行

async_runtime

standard-readme compliant Build Status Docs crates.io

用于全局生成 futures 的轻量级运行时。

已弃用:这个包已很久没有更新。它需要重写,但结果证明,大多数人更感兴趣的是基于参数的方法,而不是全局执行器方法。在此期间,我发布了 async_executorsasync_nursery,允许库在不设置全局执行器的情况下选择执行器。还有一个名为 agnostik 的包,功能大致相同。我坚信这是更好的设计,并且自那以后就没有人对全局执行器解决方案提出需求。因此,除非有严重需求,否则我不会更新这个包。

async_runtime 的目的是使生成和运行 futures 更加方便。它允许库作者调用 rt::spawn( future );,而不必获取 T: Executor,同时让客户端代码决定使用哪种类型的执行器。它避免了仅仅因为想使用几个提供异步接口的库,而这些库都依赖于它们最喜欢的运行时,就必须引入整个网络栈/反应堆。 async_runtime 努力保持快速和轻量。

一些关键功能

  • 宏属性将异步 fn 转换为同步 fn(可以在主程序、测试或任意异步 fn 上使用)
  • 尽量做到一件事并做好(不引入网络/计时依赖)
  • 支持各种执行器,包括允许生成 !Send futures 的单线程执行器。
  • 轻量级,依赖很少
  • 库作者可以生成 futures,应用作者可以决定每个线程使用的执行器。
  • WASM支持(这意味着编译在WASM上的库不需要任何特定代码,只需使用rt::spawn即可,与同步代码一样)

目录

安装

使用cargo addcargo add async_runtime

使用cargo yaml

dependencies:

  async_runtime: { version: ^0.4, package: naja_async_runtime }

使用原始Cargo.toml

[dependencies]

   async_runtime = { version = "^0.4", package = "naja_async_runtime" }

最低要求的rustc版本:1.39。

升级

升级时,请查看变更日志

功能

这些功能启用额外功能

  • :将异步fn转换为同步fn的proc宏属性。
  • juliex:juliex执行器。
  • async_std:async-std执行器。
  • localpool:localpool。
  • bindgen:由wasm-bindgen支持的执行器。

**注意**:对于库作者。您不应该在async_runtime上启用任何功能。线程级别的执行器由应用程序开发人员选择(例外:您的库正在创建线程)。

依赖项

这个crate有一些依赖项。Cargo会自动为您处理依赖项,但请注意,当您是应用程序开发人员时,您必须至少启用一个执行器,并且可能需要启用功能。

用法

基本概念是这样的。当您创建一个线程时,您调用init来决定哪个执行器将用于线程中对spawn及其朋友的调用。async_runtime确保线程池中的工作线程被设置为在同一个线程池中继续孵化。这个库中的所有顶级函数都将根据选择的执行器正确工作。一个例外是以_local结尾的函数。这些在线程池中不可用,并将返回错误。

如果在一个没有选择执行器的线程上调用spawn*,将返回错误。

可用的执行器

**警告**:一些执行器有特定的模块(如rt::localpool),这些模块提供了特定于该执行器的功能。这些存在两个原因

  1. 不同支持执行器的API不同。并不总是能够在它们之上提供统一的API。为了避免丢失功能,我们在这些模块中提供这些功能。
  2. 有时提供统一的API会带来开销,例如,将返回类型装箱(rt::spawn_handle)。由于async-std提供了JoinHandle,因此有async_std::spawn_handle来恢复该功能,而不是装箱变体。在其他执行器上,您可以使用futures库中的remote_handle来避免装箱。

LocalPool

  • 功能:localpool,在非WASM目标上默认启用
  • 属性:#[ rt::localpool ]
  • 配置:rt::Config::LocalPool
  • 目标:不在WASM上
  • 类型:单线程
  • 提供者: futures::executor::LocalPool

LocalPool 执行器作为一个单线程执行器,具有特定的设计,您应该注意。如果它在创建未来后立即轮询未来,则线程将被此操作占用,调用 spawn 的代码将无法立即返回。因此,首先进行创建然后调用阻塞方法以运行执行器。

执行器上有四个可用的方法来运行它

在这里,我不会详细介绍这些函数的功能,请查看它们的文档。目前 async_runtime 只暴露了这些函数中的 run 函数。如果您遇到需要访问其他三个函数的特定问题,请提交一个问题。

Bindgen

  • 特性: Bindgen,在 WASM 目标上默认启用
  • 属性: #[ rt::bindgen ]
  • 配置: rt::Config::Bindgen
  • 目标:仅限于 WASM
  • 类型:单线程
  • 提供者: wasm-bingen-futures

目前 WASM 上可用的唯一执行器。它像一个多线程执行器一样运行,创建的未来将立即开始轮询,无需调用 run 方法来启动执行器。

Juliex

  • 特性: juliex
  • 属性: #[ rt::juliex ]
  • 配置: rt::Config::Juliex
  • 目标:不在WASM上
  • 类型:线程池
  • 提供者:juliex

这是一个线程池。创建的工作线程将自动将 juliex 设置为线程执行器。目前无法通过 API async_runtime 暴露来更改。未来将立即轮询。

如果您有一个阻塞在顶级未来上,或者被宏属性等待的未来,一旦该未来完成,程序将结束,即使线程池中还有未完成的任务。

async_runtime 提供了 spawn_handle 方法来等待您的未来,但需要将返回的句柄装箱。否则,您可以添加自己的同步,例如通道或来自 futures 库的 join_all,以等待您的任务。futures 库还提供了 remote_handle

AsyncStd

  • 特性: async_std
  • 属性: #[ rt::async_std ]
  • 配置: rt::Config::AsyncStd
  • 目标:不在WASM上
  • 类型:线程池
  • 提供者: async-std

这是一个线程池。创建的工作线程不能自动将 AsyncStd 设置为默认执行器。这意味着 rt::spawn 将有一些开销来确保工作线程正确初始化。

警告:async-std 没有可选依赖项,因此您将拉入所有依赖项,包括网络库、mio 等,如果您不使用它们,这可能会导致膨胀。

将立即轮询将来的事件。如果您有一个顶级未来,该未来被阻塞,或者正在等待宏属性,那么一旦该未来完成,程序将结束,即使线程池中仍有未完成的任务。

async_runtime 提供了 spawn_handle 方法来等待您的未来,但需要将返回的句柄装箱。否则,您可以添加自己的同步,例如通道或来自 futures 库的 join_all,以等待您的任务。futures 库还提供了 remote_handle

block_on

  • 功能:无功能,始终可用
  • 属性:N/A
  • 配置:N/A
  • 目标:不在WASM上
  • 类型:阻塞当前线程
  • 提供者:futures::executor::block_on

请阅读[block_on]的文档。

示例

请查看存储库的示例目录

use async_runtime as rt;

// in library code:
//
fn do_something_in_parallel() -> Result<(), RtErr>
{
   rt::spawn( async
   {
      println!( "I'm running in async context" );
   })
}

// In client code we might decide that this runs in a LocalPool, instead of a threadpool:
//
[ rt::localpool ]
//
fn main()
{
   // Please look at the documentation for spawn for the possible errors here.
   //
   do_something_in_parallel().expect( "Spawn futures" );
}

// In this example we run a bunch of tasks in parallel. To verify that
// they run on different threads we make them all sleep for a second and
// measure the time passed when they finish. If they run on a threadpool
// time passed for all of them should be around 1 second.

#![ feature( duration_constants ) ]

use
{
   async_runtime as rt,

   std           :: { time::{ Duration, Instant }, thread::sleep } ,
   futures       :: { future::{ FutureExt, join_all }            } ,
};


#[ rt::juliex ]
//
async fn main()
{
   let     start = Instant::now();
   let mut tasks = Vec::new();

   for i in 0..4
   {
      // There isn't currently a convenient way to run tasks on a threadpool until all tasks have
      // finished, or until some shutdown signal is given.
      //
      // This is one of the ways tasks can synchronize and wait on eachother. Another way is to wait
      // on channels.
      //
      let (fut, handle) = async move
      {
         sleep( Duration::SECOND );

         println!( "Time elapsed at task {} end: {} second(s).", i, start.elapsed().as_secs() );

      }.remote_handle();

      rt::spawn( fut ).expect( "spawn task" );
      tasks.push( handle );
   }

   join_all( tasks ).await;
}

Wasm

要在 wasm 中使用该包,请查看存储库的示例目录中的示例。

在 WASM 上可用的唯一执行器目前是 bindgen

API

API 文档可以在docs.rs上找到。

贡献

此存储库接受贡献。可以通过 GitHub issues 提交想法、问题、功能请求和错误报告。

欢迎在 GitHub 上提交拉取请求。通过提交拉取请求,您同意您的代码可能会被修改和重新格式化,以符合项目编码风格或改进实现。如果您不希望进行可能会被拒绝的工作,请在提交拉取请求之前讨论您想看到的内容。

请针对 dev 分支提交拉取请求。

行为准则

公民行为准则第4点“不可接受的行为”中描述的任何行为都不受欢迎,并可能导致您被禁止。如果包括维护者和项目管理员在内的任何人未能尊重这些/您的限制,您有权指出。

许可证

未授权

依赖项

~1–15MB
~160K SLoC