#async-await #await #async #no-std

nightly no-std core-futures-tls

允许在no_std crate中使用async/await的libcore包装器

2个版本

0.1.1 2019年7月10日
0.1.0 2019年7月10日

#2125 in 异步

Download history 28/week @ 2024-03-28 23/week @ 2024-04-04 1/week @ 2024-04-18 2/week @ 2024-04-25

每月76次下载
用于 nrf52840-platform

Apache-2.0 OR MIT

12KB
71

core-futures-tls

一个libcore包装器,允许从no_std crate中使用async/await,前提是它们的目标支持ELF TLS(即#[thread_local]属性)。

用法

在您的Cargo.toml中添加以下内容

[dependencies]
core = { package = "core-futures-tls", version = "0.1.0" }

原因

目前,async/await无法从libcore中使用。从no_std crate中调用.await将产生以下错误

error[E0433]: failed to resolve: could not find `poll_with_tls_context` in `future`
error[E0433]: failed to resolve: could not find `from_generator` in `future`

这是因为await降低到调用函数::core::futures::poll_with_tls_context::core::futures::from_generator以设置包含当前任务的每个线程的上下文。然而,这些函数不存在。等效函数定义在libstd中。它们设置一个包含正在执行的当前任务的线程局部变量。在轮询future时,将检索此任务以调用future的poll函数。

如前所述,这些函数的libstd版本使用线程局部变量,这仅在rust的libstd中通过thread_local!宏支持 - 而在libcore中不存在。然而,有一个替代方案:(不稳定)的#[thread_local]属性,它使用ELF TLS。请注意,ELF TLS不可移植到所有目标 - 它需要由操作系统、加载器等支持...

以下是一个使用thread_local属性的简单示例

#![feature(thread_local)]
use core::cell::Cell;
#[thread_local]
static TLS_CX: Cell<i32> = Cell::new(1);

使用这个技巧,我们可以复制粘贴libstd的poll_with_tls_context/from_generator函数实现,但用#[thread_local]宏替换thread_local!宏。很简单。

包装libcore

这个技巧不错,但是编译自定义的libcore很麻烦。相反,我们将包装libcore,暴露我们的libcore,它只是重新导出真实的libcore的函数,并添加我们自己的额外内容。令人惊讶的是,这可以通过简单地声明一个具有package属性设置为我们的“真实”crates.io包名的core依赖项来实现。这将欺骗cargo将我们的包装器核心作为真实的libcore传递给rustc。

这就是全部。这个crate所做的只是重新导出libcore,在未来模块中添加一些函数。你只需要在Cargo.toml中使用以下内容,就可以使用它,rust将愉快地使用core-futures-tls,就像它使用libcore一样。

[dependencies]
core = { package = "core-futures-tls", version = "0.1.0" }

结束语

虽然这个crate仍然使用TLS,但应该可以创建一个版本,该版本将单线程系统(如微控制器)的线程局部上下文存储在全局中。这留作读者的练习。

无运行时依赖