2个版本
0.1.1 | 2019年7月10日 |
---|---|
0.1.0 | 2019年7月10日 |
#2125 in 异步
每月76次下载
用于 nrf52840-platform
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,但应该可以创建一个版本,该版本将单线程系统(如微控制器)的线程局部上下文存储在全局中。这留作读者的练习。