From 5c511c36e82a13e33c68bc8913335aa019691cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=9B=8B=E7=96=BC=E7=9A=84=E8=9B=8B=E8=9B=8B?= Date: Sat, 26 Aug 2023 15:11:26 +0800 Subject: [PATCH 1/6] =?UTF-8?q?Update=20global-variable.md(next=5Fid?= =?UTF-8?q?=E5=8F=96=E5=80=BC=E9=94=99=E8=AF=AF=EF=BC=9F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atomic*::fetch_* 函数返回值为上一个值,next_id的取值是不是错了? --- src/advance/global-variable.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/advance/global-variable.md b/src/advance/global-variable.md index 0148ee9c..66492d87 100644 --- a/src/advance/global-variable.md +++ b/src/advance/global-variable.md @@ -93,7 +93,8 @@ fn generate_id()->usize{ if current_val > MAX_ID{ panic!("Factory ids overflowed"); } - let next_id = GLOBAL_ID_COUNTER.fetch_add(1, Ordering::Relaxed); + GLOBAL_ID_COUNTER.fetch_add(1, Ordering::Relaxed) + let next_id = GLOBAL_ID_COUNTER.load(Ordering::Relaxed); if next_id > MAX_ID{ panic!("Factory ids overflowed"); } From 1bd961357942367e038e747ee9879833275bb9ca Mon Sep 17 00:00:00 2001 From: sd44 Date: Sat, 26 Aug 2023 18:41:52 +0800 Subject: [PATCH 2/6] =?UTF-8?q?OnceCell=E5=92=8COnceLock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/advance/global-variable.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/advance/global-variable.md b/src/advance/global-variable.md index 66492d87..a67f8ea8 100644 --- a/src/advance/global-variable.md +++ b/src/advance/global-variable.md @@ -315,13 +315,21 @@ fn main() { ## 标准库中的 OnceCell -在 `Rust` 标准库中提供 `lazy::OnceCell` 和 `lazy::SyncOnceCell` 两种 `Cell`,前者用于单线程,后者用于多线程,它们用来存储堆上的信息,并且具有最多只能赋值一次的特性。 如实现一个多线程的日志组件 `Logger`: +在 `Rust` 标准库中提供 `lazy::OnceCell` 和 `lazy::SyncOnceCell` (在 `Rust` +1.70.0版本及以上的标准库中,更改为 `cell::OnceCell` 和 `sync::OnceLock` )两种 +`Cell` ,前者用于单线程,后者用于多线程,它们用来存储堆上的信息,并且具有最 +多只能赋值一次的特性。 如实现一个多线程的日志组件 `Logger`: + ```rust +// 低于Rust 1.70版本 #![feature(once_cell)] use std::{lazy::SyncOnceCell, thread}; +// Rust 1.70版本以上 +// use std::{sync::OnceLock, thread}; + fn main() { // 子线程中调用 let handle = thread::spawn(|| { @@ -342,8 +350,12 @@ fn main() { #[derive(Debug)] struct Logger; +// 低于Rust 1.70版本 static LOGGER: SyncOnceCell = SyncOnceCell::new(); +// Rust 1.70版本以上 +// static LOGGER: OnceLock = OnceLock::new(); + impl Logger { fn global() -> &'static Logger { // 获取或初始化 Logger From f8a6ae7ed571a565433f205055b806ba742b1507 Mon Sep 17 00:00:00 2001 From: sd44 Date: Sat, 26 Aug 2023 18:55:54 +0800 Subject: [PATCH 3/6] =?UTF-8?q?OnceCell=E5=92=8COnceLock=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/advance/global-variable.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/advance/global-variable.md b/src/advance/global-variable.md index a67f8ea8..80d8c47e 100644 --- a/src/advance/global-variable.md +++ b/src/advance/global-variable.md @@ -315,19 +315,19 @@ fn main() { ## 标准库中的 OnceCell -在 `Rust` 标准库中提供 `lazy::OnceCell` 和 `lazy::SyncOnceCell` (在 `Rust` -1.70.0版本及以上的标准库中,更改为 `cell::OnceCell` 和 `sync::OnceLock` )两种 +在 `Rust` 标准库中提供了实验性的 `lazy::OnceCell` 和 `lazy::SyncOnceCell` (在 `Rust` +1.70.0版本及以上的标准库中,替换为稳定的 `cell::OnceCell` 和 `sync::OnceLock` )两种 `Cell` ,前者用于单线程,后者用于多线程,它们用来存储堆上的信息,并且具有最 多只能赋值一次的特性。 如实现一个多线程的日志组件 `Logger`: ```rust -// 低于Rust 1.70版本 +// 低于Rust 1.70版本中, OnceCell 和 SyncOnceCell 的API为实验性的 , +// 需启用特性 `#![feature(once_cell)]`。 #![feature(once_cell)] - use std::{lazy::SyncOnceCell, thread}; -// Rust 1.70版本以上 +// Rust 1.70版本以上, // use std::{sync::OnceLock, thread}; fn main() { From 85270bbdae9c8025f21d30d494983001368c46ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=9B=8B=E7=96=BC=E7=9A=84=E8=9B=8B=E8=9B=8B?= Date: Thu, 7 Sep 2023 09:39:23 +0800 Subject: [PATCH 4/6] =?UTF-8?q?Update=20macro.md=EF=BC=8C=E5=8E=9F?= =?UTF-8?q?=E6=9D=A5=E4=BB=A3=E7=A0=81=E6=BC=8F=E5=8A=A0=E9=80=97=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/advance/macro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/advance/macro.md b/src/advance/macro.md index 1369857f..137c1d48 100644 --- a/src/advance/macro.md +++ b/src/advance/macro.md @@ -393,11 +393,11 @@ pub struct User <'a, T> { DeriveInput { // --snip-- vis: Visibility, - generics: Generics ident: Ident { ident: "Sunfei", span: #0 bytes(95..103) }, + generics: Generics, // Data是一个枚举,分别是DataStruct,DataEnum,DataUnion,这里以 DataStruct 为例 data: Data( DataStruct { From f842616a202f7dacc27930d58ce0962f0342c17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=9B=8B=E7=96=BC=E7=9A=84=E8=9B=8B=E8=9B=8B?= Date: Thu, 7 Sep 2023 11:56:33 +0800 Subject: [PATCH 5/6] =?UTF-8?q?Update=20macro.md=20fields=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/advance/macro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/advance/macro.md b/src/advance/macro.md index 1369857f..85740ee2 100644 --- a/src/advance/macro.md +++ b/src/advance/macro.md @@ -413,7 +413,7 @@ DeriveInput { 以上就是源代码 `struct Sunfei;` 解析后的结果,里面有几点值得注意: -- `fields: Fields` 是一个枚举类型,FieldsNamed,FieldsUnnamed,FieldsUnnamed, 分别表示显示命名结构(如例子所示),匿名字段的结构(例如 struct A(u8);),和无字段定义的结构(例如 struct A;) +- `fields: Fields` 是一个枚举类型,`Fields::Named`, `Fields::Unnamed`, `Fields::Unit` 分别表示结构体中的显式命名字段(如例子所示),元组结构或元组变体中的匿名字段(例如`Some(T)`),单元类型或单元变体(例如`None` )。 - `ident: "Sunfei"` 说明类型名称为 `Sunfei`, `ident` 是标识符 `identifier` 的简写 如果想要了解更多的信息,可以查看 [`syn` 文档](https://docs.rs/syn/1.0/syn/struct.DeriveInput.html)。 From 13cce75ff676a0894775e4927823be1da98eba29 Mon Sep 17 00:00:00 2001 From: sd44 Date: Fri, 8 Sep 2023 04:33:05 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=09=E4=BF=AE=E6=94=B9=EF=BC=9A=20=20=20=20?= =?UTF-8?q?=20macro.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/advance/macro.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/advance/macro.md b/src/advance/macro.md index 47a640f9..31cddee5 100644 --- a/src/advance/macro.md +++ b/src/advance/macro.md @@ -366,7 +366,7 @@ pub fn hello_macro_derive(input: TokenStream) -> TokenStream { 这个函数的签名我们在之前已经介绍过,总之,这种形式的过程宏定义是相当通用的,下面来分析下这段代码。 -首先有一点,对于绝大多数过程宏而言,这段代码往往只在 `impl_hello_macro(&ast)` 中的实现有所区别,对于其它部分基本都是一致的,例如包的引入、宏函数的签名、语法树构建等。 +首先有一点,对于绝大多数过程宏而言,这段代码往往只在 `impl_hello_macro(&ast)` 中的实现有所区别,对于其它部分基本都是一致的,如包的引入、宏函数的签名、语法树构建等。 `proc_macro` 包是 Rust 自带的,因此无需在 `Cargo.toml` 中引入依赖,它包含了相关的编译器 `API`,可以用于读取和操作 Rust 源代码。 @@ -378,10 +378,10 @@ derive过程宏只能用在struct/enum/union上,多数用在结构体上,我 ```rust // vis,可视范围 ident,标识符 generic,范型 fields: 结构体的字段 pub struct User <'a, T> { - + // vis ident type pub name: &'a T, - + } ``` @@ -413,7 +413,7 @@ DeriveInput { 以上就是源代码 `struct Sunfei;` 解析后的结果,里面有几点值得注意: -- `fields: Fields` 是一个枚举类型,`Fields::Named`, `Fields::Unnamed`, `Fields::Unit` 分别表示结构体中的显式命名字段(如例子所示),元组结构或元组变体中的匿名字段(例如`Some(T)`),单元类型或单元变体(例如`None` )。 +- `fields: Fields` 是一个枚举类型,`Fields::Named`, `Fields::Unnamed`, `Fields::Unit` 分别表示结构体中的显式命名字段(如例子所示),元组或元组变体中的匿名字段(例如`Some(T)`),单元类型或单元变体字段(例如`None` )。 - `ident: "Sunfei"` 说明类型名称为 `Sunfei`, `ident` 是标识符 `identifier` 的简写 如果想要了解更多的信息,可以查看 [`syn` 文档](https://docs.rs/syn/1.0/syn/struct.DeriveInput.html)。 @@ -451,7 +451,7 @@ fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream { 在运行之前,可以显示用 expand 展开宏,观察是否有错误或是否符合预期: ```shell -$ cargo expand +$ cargo expand --lib hello_macro ``` ```rust struct Sunfei; @@ -486,8 +486,8 @@ fn main() { } ``` -从展开的代码也能看出derive宏的特性,struct Sunfei; 和 struct Sunface; 都被保留了,也就是说最后 impl_hello_macro() 返回的token被加到结构体后面,这和类属性宏可以修改输入 -的token是不一样的,input的token并不能被修改 +从展开的代码也能看出derive宏的特性,`struct Sunfei;` 和 `struct Sunface;` 都被保留了,也就是说最后 `impl_hello_macro()` 返回的token被加到结构体后面,这和类属性宏可以修改输入 +的token是不一样的,input的token并不能被修改。 至此,过程宏的定义、特征定义、主体代码都已经完成,运行下试试: @@ -566,7 +566,7 @@ struct User { } fn main() { - + } ```