|
|
|
@ -0,0 +1,75 @@
|
|
|
|
|
# Rust 新版解读 | 1.63 | 重点: Socped threads
|
|
|
|
|
|
|
|
|
|
> Rust 1.63 官方 release doc: [Announcing Rust 1.63.0 | Rust Blog](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html)
|
|
|
|
|
|
|
|
|
|
通过 [rustup](https://www.rust-lang.org/tools/install) 安装的同学可以使用以下命令升级到 1.61 版本:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ rustup update stable
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 区域线程 Scoped threads
|
|
|
|
|
|
|
|
|
|
Rust 从 1.0 版本起,就可以使用 `std::thread::spawn` 来创建一个线程,但是这个函数要求了其生成的线程必须拥有任何传递进去的参数的所有权,也就是说你不能把引用数据传递进去。在一些线程会在方法末尾退出的情况下(通常使用 `join()` 方法),这个严格的约束显得不必要,在此之前也通常使用 `Arc` 包裹数据的的方法来妥协。
|
|
|
|
|
|
|
|
|
|
随着 1.63 版本的推出,标准库新增了**区域线程**,允许在区域 `scope` 内创建使用当前调用栈内引用数据的线程。`std::thread::scope` 的API保证其中创建的线程会在自身返回前推出,也就允许安全的借用数据。看下面的例子,在 `scope` 内创建两个线程来,分别借用了数据:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
let mut a = vec![1, 2, 3];
|
|
|
|
|
let mut x = 0;
|
|
|
|
|
|
|
|
|
|
std::thread::scope(|s| {
|
|
|
|
|
s.spawn(|| {
|
|
|
|
|
println!("hello from the first scoped thread");
|
|
|
|
|
// 可以借用变量 `a`
|
|
|
|
|
dbg!(&a);
|
|
|
|
|
});
|
|
|
|
|
s.spawn(|| {
|
|
|
|
|
println!("hello from the second scoped thread");
|
|
|
|
|
// 没有其它线程在使用,所以也可以可变借用 `x`
|
|
|
|
|
x += a[0] + a[2];
|
|
|
|
|
});
|
|
|
|
|
println!("hello from the main thread");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Scope 退出后,可以继续修改、访问变量。
|
|
|
|
|
a.push(4);
|
|
|
|
|
assert_eq!(x, a.len());
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Rust 对原始文件描述符/句柄的所有权
|
|
|
|
|
|
|
|
|
|
之前 Rust 代码在使用平台相关 API ,涉及到文件描述符(file descriptor on unix)或句柄(handles on windows)的时候,都是直接使用对应的描述符(比如,`c_int` alias `RawFd`)。因此类型系统无法判断 API 是会获取文件描述符的所有权,还是仅仅借用它。
|
|
|
|
|
|
|
|
|
|
现在,Rust 提供了封装类型诸如 `BorrowedFd` 和 `OwnedFd`。这些封装类型都标记为了 `#[repr(transparent)]`,意味着 `extern "C"` 绑定下也可以直接使用这些类型来编码所有权语义。完整的封装类型参见原文下的 [stabilized apis in 1.63](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html#stabilized-apis)
|
|
|
|
|
|
|
|
|
|
## `Mutex`, `RwLock`, `Condvar` 作为静态变量
|
|
|
|
|
|
|
|
|
|
`Condvar::new`, `Mutex::new` 和 `RwLock::new` 可以在 `const` 上下文里被调用了,不必再使用 `lazy_static` 库来写全局静态的 `Mutex`, `RwLock`, `Condvar` 了。
|
|
|
|
|
|
|
|
|
|
## Turbofish 可用于含有 `impl Trait` 的泛型函数上
|
|
|
|
|
|
|
|
|
|
诸如 `fn foo<T>(value: T, f: impl Copy)` 的函数签名,使用 Turbofish `foo::<u32>(3,3)` 来指定 `T` 的具体类型会出现编译错误:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
|
|
|
|
|
--> src/lib.rs:4:11
|
|
|
|
|
|
|
|
|
|
|
4 | foo::<u32>(3, 3);
|
|
|
|
|
| ^^^ explicit generic argument not allowed
|
|
|
|
|
|
|
|
|
|
|
= note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
1.63里这个限制被放松了,显式泛型类型可以用 Turbofish 来指定了。不过 `impl Trait` 参数,尽管已经脱糖(desugare)成了泛型,因为还是不透明的所以无法通过 Turbofish 指定。
|
|
|
|
|
|
|
|
|
|
## 完成了 Non-lexical-lifetime 的生命周期检查器的迁移
|
|
|
|
|
|
|
|
|
|
1.63 的rustc,完全删除了之前的词法借用检查,完全启用了新的 NLL 借用检查器。这不会对编译结果有任何变化,但对编译器的借用错误检查有优化效果。
|
|
|
|
|
|
|
|
|
|
如果对NLL不了解,在本书 [引用与借用](https://course.rs/basic/ownership/borrowing.html#NLL) 一章里有介绍。
|
|
|
|
|
|
|
|
|
|
或者看官方博客的介绍 [NLL](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#non-lexical-lifetimes)
|
|
|
|
|
|
|
|
|
|
更详细内容可以看原博客 [blog](https://blog.rust-lang.org/2022/08/05/nll-by-default.html)
|
|
|
|
|
|