sui_rust/ch03/s2_async_await.rs
1//! 第三章:Rust 异步编程概念
2//!
3//! # 3.2 异步 编程 模型
4//!
5//! - [smol](https://github.com/smol-rs/smol)
6//! - Future
7//! - 生成器 与 协程
8//! - Pin 与 UnPin
9//! - Async/Await
10//!
11//!
12
13/**
14
15 让我们先从建立异步编程模型的整体概念框架开始,先不深入细节。
16
17 **Rust 提供的异步并发相比于其他语言有什么特点?**
18
19 1. Rust 语言只是提供一个零成本的异步编程抽象,而不内置运行时。
20 2. 基于 Generator 实现的 Future,在 Future 基础上 提供 async/await 语法糖。本质是一个状态机。
21
22 查看 README 和其他编程语言比较的图示。
23
24 **为什么需要异步?**
25
26 1. 对极致性能的追求。
27 2. 对编程体验的追求。
28
29 **异步编程模型发展阶段:**
30
31 1. Callback
32 2. Promise/Future
33 3. async/await
34
35 可在项目 README 查看回调地狱示例图。
36
37 ```text
38 A
39 +------+
40 | |
41 | |
42 | +-------------------+
43 | | |
44 | | |
45 | | Bv
46 +------+ +-----+
47 | | | |
48 | | | do1 |
49 | | | |
50 | | +-----+
51 | | | |
52 | | | do2 |
53 | | +-+---+
54 | | |
55 | | |
56 | A | |
57 +------+ |
58 | | |
59 | | |
60 | | |
61 | | <----------------+
62 | |
63 | |
64 | |
65 +------+
66
67 ```
68
69 早期 Rust 异步写法示意:
70
71 ```rust
72 let future = id_rpc(&my_server).and_then(|id| {
73 get_row(id)
74 }).map(|row| {
75 json::encode(row)
76 }).and_then(|encoded| {
77 write_string(my_socket, encoded)
78 });
79 ```
80
81 这样写会存在大量内嵌 Future,开发体验不好。
82
83 引入 async/await 之后:
84
85 ```rust
86 let id = id_rpc(&my_server).await;
87 let row = get_row(id).await;
88 let encoded = json::encode(row);
89 write_string(my_socket, encoded).await;
90 ```
91
92 拥有了和同步代码一致的体验。
93
94 **异步任务可看作是一种绿色线程**
95
96 查看 README 相关图示
97
98 可以说,异步任务的行为是模仿 线程 来抽象。
99
100 1. 线程在进程内,异步任务在线程内。
101 2. 线程可被调度切换(Linux默认抢占式),异步任务也可以被调度(协作式而非抢占式)。区别在于,异步任务只在用户态,没有线程的上下文切换开销。
102 3. 线程有上下文信息,异步任务也有上下文信息。
103 4. 线程间可以通信,异步任务之间也可以通信。
104 5. 线程间有竞争,异步任务之间也有竞争。
105
106 整个异步编程概念,包括异步语法、异步运行时都是围绕如何建立这种「绿色线程」抽象而成的。
107
108*/
109pub fn a_async_intro() {}
110
111/**
112
113 # Future 和 Futures-rs 概要
114
115 - [Future](https://doc.rust-lang.org/std/future/index.html) and [task](https://doc.rust-lang.org/std/task/index.html)
116 - [futures-rs](https://github.com/rust-lang/futures-rs)
117
118
119
120*/
121
122pub fn b_futures_simple_intro() {}
123
124/**
125
126 通过实现一个简单的 async/await echo server 来理解 Futures
127
128 代码示例参见本仓库内:async-echo-server
129
130 通过代码实现 简单的异步运行时(executor+reactor)
131
132*/
133
134pub fn c_async_await_echo() {}
135
136/**
137
138 # 深入理解 Future 和 Futures-rs
139
140
141 回顾 Rust 异步 task 模型
142
143 ```text
144 +------------------------------------------------------------------+
145 | |
146 | +--------------------------------------------------------+ |
147 | | | |
148 | | +-------------------------------------------------+ | |
149 | | |-------------+ +----------+ +--------------+ | | |
150 | | || futureobj | | futureobj| | futureobj | | | |
151 | | +-------------+ +----------+ +--------------+ | | |
152 | | | 协 程 task | | |
153 | | +-------------------------------------------------+ | |
154 | | | |
155 | | 线 程 | |
156 | +--------------------------------------------------------+ |
157 | |
158 | |
159 | +--------------------------------------------------------+ |
160 | | +--------------------------------------------------+ | |
161 | | | | | |
162 | | | +------------+ +-------------------------------+ | |
163 | | | | futureobj | | futureobj || futureobj || | |
164 | | | +------------+ +-------------------------------+ | |
165 | | | 协 程 task | | |
166 | | +--------------------------------------------------+ | |
167 | | 线 程 | |
168 | +--------------------------------------------------------+ |
169 | |
170 | 进 程 |
171 +------------------------------------------------------------------+
172
173
174 ```
175
176
177 1. 理解 leaf-futures vs Non-leaf-futures (async/await)
178 2. 理解 Waker:
179
180 > 当事件源注册该Future将在某个事件上等待时,它必须存储唤醒程序,以便以后可以调用唤醒来开始唤醒阶段。
181 > 为了引入并发性,能够同时等待多个事件非常重要,因此唤醒器不可能由单个事件源唯一拥有。 结果,Waker类型需要是实现 Clone 的。
182
183 - [https://doc.rust-lang.org/std/task/struct.Waker.html](https://doc.rust-lang.org/std/task/struct.Waker.html)
184
185
186 3. 理解并发(waker 并发 和 poll 并发)
187
188
189 深入 Futures-rs:
190
191 - [Future](https://doc.rust-lang.org/std/future/index.html) and [task](https://doc.rust-lang.org/std/task/index.html)
192 - [futures-rs](https://github.com/rust-lang/futures-rs)
193 - [futures-lite](https://github.com/smol-rs/futures-lite)
194
195
196*/
197
198pub fn d_futures_rs() {}
199
200/**
201
202
203 # 异步实现细节:生成器 与 协程
204
205 ## 历史
206
207 处理异步事件的三种方式:
208 - Callback
209 - Promise/Future
210 - async/await
211
212 async/await 是目前体验最好的方式,Rust 要支持它并不容易。
213
214 ## async/await 语法介绍
215
216 参考:[Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html)
217
218 `async` 两种用法:`async fn ` 函数 和 `async {}` 块。
219
220 ```rust
221 // async 函数,真正会返回 `Future<Output = u8>`,而不是表面看上去的 `u8`
222 async fn foo() -> u8 { 5 }
223
224 // async 块用法,返回 `impl Future<Output = u8>`
225 fn bar() -> impl Future<Output = u8> {
226 // 这里 `async` 块返回 `impl Future<Output = u8>`
227 async {
228 let x: u8 = foo().await;
229 x + 5
230 }
231 }
232 ```
233
234 `await` 将暂停当前函数的执行,直到执行者将 Future 结束为止。这为其他 Future 任务提供了计算的机会。
235
236
237 ## 生成器
238
239 Future 底层实现依赖于 生成器。 `async/await` 对应底层生成器 `resume/yield` 。
240
241 ```rust
242 #![feature(generators, generator_trait)]
243 use std::ops::Generator;
244 use std::pin::Pin;
245
246 fn main() {
247 let mut gen = || {
248 yield 1;
249 yield 2;
250 yield 3;
251 return 4;
252 };
253 // for _ in 0..4 {
254 // // 为了给嵌入式支持异步,多传入了一个空的unit给resume方法
255 // let c = Pin::new(&mut gen).resume(());
256 // println!("{:?}", c);
257 // }
258
259
260 let c = Pin::new(&mut gen).resume(());
261 println!("{:?}", c);
262 let c = Pin::new(&mut gen).resume(());
263 println!("{:?}", c);
264 let c = Pin::new(&mut gen).resume(());
265 println!("{:?}", c);
266 let c = Pin::new(&mut gen).resume(());
267 println!("{:?}", c);
268 }
269
270 ```
271
272 生成等价代码:
273
274 ```rust
275 #![allow(unused)]
276 #![feature(generators, generator_trait)]
277 use std::ops::{Generator, GeneratorState};
278 use std::pin::Pin;
279
280 enum __Gen {
281 // (0) 初始状态
282 Start,
283 // (1) resume方法执行以后
284 State1(State1),
285 // (2) resume方法执行以后
286 State2(State2),
287 // (3) resume方法执行以后
288 State3(State3),
289 // (4) resume方法执行以后,正好完成
290 Done
291 }
292
293
294 struct State1 { x: u64 }
295 struct State2 { x: u64 }
296 struct State3 { x: u64 }
297
298 impl Generator for __Gen {
299 type Yield = u64;
300 type Return = u64;
301
302 fn resume(self: Pin<&mut Self>, _: ()) -> GeneratorState<u64, u64> {
303 let mut_ref = self.get_mut();
304 match std::mem::replace(mut_ref, __Gen::Done) {
305 __Gen::Start => {
306 *mut_ref = __Gen::State1(State1{x: 1});
307 GeneratorState::Yielded(1)
308 }
309 __Gen::State1(State1{x: 1}) => {
310 *mut_ref = __Gen::State2(State2{x: 2});
311 GeneratorState::Yielded(2)
312 }
313 __Gen::State2(State2{x: 2}) => {
314 *mut_ref = __Gen::State3(State3{x: 3});
315 GeneratorState::Yielded(3)
316 }
317 __Gen::State3(State3{x: 3}) => {
318 *mut_ref = __Gen::Done;
319 GeneratorState::Complete(4)
320 }
321 _ => {
322 panic!("generator resumed after completion")
323 }
324 }
325 }
326 }
327
328 fn main(){
329 let mut gen = {
330 __Gen::Start
331 };
332
333 for _ in 0..4 {
334 println!("{:?}", unsafe{ Pin::new(&mut gen).resume(())});
335 }
336 }
337 ```
338
339 生成器基本用法:
340
341 ```rust
342
343 #![allow(unused)]
344 #![feature(generators, generator_trait)]
345 use std::pin::Pin;
346
347 use std::ops::Generator;
348
349 pub fn up_to(limit: u64) -> impl Generator<Yield = u64, Return = u64> {
350 move || {
351 for x in 0..limit {
352 yield x;
353 }
354 return limit;
355 }
356 }
357 fn main(){
358 let a = 10;
359 let mut b = up_to(a);
360 unsafe {
361 for _ in 0..=10{
362 let c = Pin::new(&mut b).resume(());
363 println!("{:?}", c);
364 }
365 }
366 }
367
368 ```
369
370 生成器变身为迭代器:
371
372 ```rust
373 #![allow(unused)]
374 #![feature(generators, generator_trait)]
375 use std::pin::Pin;
376
377 use std::ops::{Generator, GeneratorState};
378
379 pub fn up_to() -> impl Generator<Yield = u64, Return = ()> {
380 move || {
381 let mut x = 0;
382 loop {
383 x += 1;
384 yield x;
385 }
386 return ();
387 }
388 }
389 fn main(){
390 let mut gen = up_to();
391 unsafe {
392 for _ in 0..10{
393 match Pin::new(&mut gen).resume(()) {
394 GeneratorState::Yielded(i) => println!("{:?}", i),
395 _ => println!("Completed"),
396 }
397 }
398 }
399 }
400 ```
401
402 生成器变身为 Future:
403
404 ```rust
405
406 #![allow(unused)]
407 #![feature(generators, generator_trait)]
408
409 use std::ops::{Generator, GeneratorState};
410 use std::pin::Pin;
411
412 pub fn up_to(limit: u64) -> impl Generator<Yield = (), Return = Result<u64, ()>> {
413 move || {
414 for x in 0..limit {
415 yield ();
416 }
417 return Ok(limit);
418 }
419 }
420 fn main(){
421 let limit = 2;
422 let mut gen = up_to(limit);
423 unsafe {
424 for i in 0..=limit{
425 match Pin::new(&mut gen).resume(()) {
426 GeneratorState::Yielded(v) => println!("resume {:?} : Pending", i),
427 GeneratorState::Complete(v) => println!("resume {:?} : Ready", i),
428 }
429 }
430 }
431 }
432 ```
433
434
435 跨 yield 借用会报错:
436
437 ```rust
438 #![allow(unused)]
439 #![feature(generators, generator_trait)]
440
441 use std::ops::Generator;
442 use std::pin::Pin;
443
444 pub fn up_to(limit: u64) -> impl Generator<Yield = u64, Return = u64> {
445 move || {
446 let a = 5;
447 let ref_a = &a;
448 for x in 0..limit {
449 yield x;
450 if x == 5{
451 yield *ref_a;
452 }
453 }
454 return limit;
455 }
456 }
457 fn main(){
458 let a = 10;
459 let mut b = up_to(a);
460 unsafe {
461 for _ in 0..=10{
462 let c = Pin::new(&mut b).resume(());
463 println!("{:?}", c);
464 }
465 }
466 }
467 ```
468
469
470 自引用结构:
471
472 ```rust
473 #![feature(generators, generator_trait)]
474 use std::ops::Generator;
475 use std::pin::Pin;
476 fn main(){
477 let mut generator = move || {
478 let to_borrow = String::from("Hello");
479 let borrowed = &to_borrow;
480 // error[E0626]: borrow may still be in use when generator yields
481 yield borrowed.len();
482 println!("{} world!", borrowed);
483 };
484 }
485
486 ```
487
488 模拟底层实现 generator :
489
490 ```rust
491 #![allow(unused)]
492 #![feature(never_type)] // Force nightly compiler to be used in playground
493 // by betting on it's true that this type is named after it's stabilization date...
494 pub fn main() {
495 let mut gen = GeneratorA::start();
496 let mut gen2 = GeneratorA::start();
497
498 if let GeneratorState::Yielded(n) = gen.resume() {
499 println!("Got value {}", n);
500 }
501
502 // std::mem::swap(&mut gen, &mut gen2); // <--- Big problem!
503
504 if let GeneratorState::Yielded(n) = gen2.resume() {
505 println!("Got value {}", n);
506 }
507
508 // This would now start gen2 since we swapped them.
509 if let GeneratorState::Complete(()) = gen.resume() {
510 ()
511 };
512
513 if let GeneratorState::Complete(()) = gen2.resume() {
514 ()
515 };
516 }
517 enum GeneratorState<Y, R> {
518 Yielded(Y),
519 Complete(R),
520 }
521
522 trait Generator {
523 type Yield;
524 type Return;
525 fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
526 }
527
528 enum GeneratorA {
529 Enter,
530 Yield1 {
531 to_borrow: String,
532 borrowed: *const String,
533 },
534 Exit,
535 }
536
537 impl GeneratorA {
538 fn start() -> Self {
539 GeneratorA::Enter
540 }
541 }
542 impl Generator for GeneratorA {
543 type Yield = usize;
544 type Return = ();
545 fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
546 match self {
547 GeneratorA::Enter => {
548 let to_borrow = String::from("Hello");
549 let borrowed = &to_borrow;
550 let res = borrowed.len();
551 *self = GeneratorA::Yield1 {to_borrow, borrowed: std::ptr::null()};
552
553 // We set the self-reference here
554 if let GeneratorA::Yield1 {to_borrow, borrowed} = self {
555 *borrowed = to_borrow;
556 }
557
558 GeneratorState::Yielded(res)
559 }
560
561 GeneratorA::Yield1 {borrowed, ..} => {
562 let borrowed: &String = unsafe {&**borrowed};
563 println!("{} world", borrowed);
564 *self = GeneratorA::Exit;
565 GeneratorState::Complete(())
566 }
567 GeneratorA::Exit => panic!("Can't advance an exited generator!"),
568 }
569 }
570 }
571 ```
572 上面代码在 Safe Rust 下是存在问题的,有 UB 风险。
573
574
575 用 Pin 修正:
576
577 ```rust
578 #![feature(generators, generator_trait)]
579 use std::ops::{Generator, GeneratorState};
580
581
582 pub fn main() {
583 // 使用 static 关键字创建 immovable 生成器
584 let gen1 = static || {
585 let to_borrow = String::from("Hello");
586 let borrowed = &to_borrow;
587 yield borrowed.len();
588 println!("{} world!", borrowed);
589 };
590
591 let gen2 = static || {
592 let to_borrow = String::from("Hello");
593 let borrowed = &to_borrow;
594 yield borrowed.len();
595 println!("{} world!", borrowed);
596 };
597
598 let mut pinned1 = Box::pin(gen1);
599 let mut pinned2 = Box::pin(gen2);
600
601 if let GeneratorState::Yielded(n) = pinned1.as_mut().resume(()) {
602 println!("Gen1 got value {}", n);
603 }
604
605 if let GeneratorState::Yielded(n) = pinned2.as_mut().resume(()) {
606 println!("Gen2 got value {}", n);
607 };
608
609 let _ = pinned1.as_mut().resume(());
610 let _ = pinned2.as_mut().resume(());
611 }
612
613 ```
614
615
616 第三方库 genawaiter:stable rust 实现 generator 。
617
618 [https://github.com/whatisaphone/genawaiter](https://github.com/whatisaphone/genawaiter)
619
620*/
621pub fn e_generator() {}
622
623/**
624
625
626 ### 前奏
627
628
629 Safe Rust 无法构建自引用结构体:
630
631 ```rust
632 struct SelfReferential<'a> {
633 a: String,
634 b: &'a String,
635 }
636
637 fn main() {
638 let a = String::from("Hello");
639 let _sr = SelfReferential { a, b: &a }; // error: borrow of moved value: `a`
640 }
641 ```
642
643 另一个示例:即便使用 `Box<T>` 放到堆上,也存在风险:
644
645 ```rust
646 struct SelfReferential {
647 self_ptr: *const Self,
648 }
649
650 fn main() {
651 let mut heap_value = Box::new(SelfReferential {
652 self_ptr: 0 as *const _,
653 });
654 let ptr = &*heap_value as *const SelfReferential;
655 heap_value.self_ptr = ptr;
656 println!("heap value at: {:p}", heap_value);
657 println!("internal reference: {:p}", heap_value.self_ptr);
658
659 // 风险代码
660 let stack_value = mem::replace(&mut *heap_value, SelfReferential {
661 self_ptr: 0 as *const _,
662 _pin: PhantomPinned,
663 });
664 println!("value at: {:p}", &stack_value);
665 println!("internal reference: {:p}", stack_value.self_ptr);
666 }
667
668 ```
669
670
671 使用指针来构建,但是有安全风险:
672
673 ```rust
674 #[derive(Debug)]
675 struct SelfReferential {
676 a: String,
677 b: *const String,
678 }
679
680 impl SelfReferential {
681 fn new(txt: &str) -> Self {
682 Self {
683 a: String::from(txt),
684 b: std::ptr::null(),
685 }
686 }
687
688 fn init(&mut self) {
689 let self_ref: *const String = &self.a;
690 self.b = self_ref;
691 }
692
693 fn a(&self) -> &str {
694 &self.a
695 }
696
697 fn b(&self) -> &String {
698 unsafe {&*(self.b)}
699 }
700 }
701
702 fn main() {
703 let mut sf1 = SelfReferential::new("test1");
704 sf1.init();
705 let mut sf2 = SelfReferential::new("test2");
706 sf2.init();
707
708 println!("a: {}, b: {}", sf1.a(), sf1.b());
709 println!("a: {:p}, b: {:p}, t: {:p}", &(sf1.a), sf1.b, &(sf2.a));
710 // 使用swap()函数交换两者,这里发生了move
711 std::mem::swap(&mut sf1, &mut sf2);
712
713
714 sf1.a = "I've totally changed now!".to_string();
715 println!("a: {}, b: {}", sf2.a(), sf2.b());
716 println!("a: {:p}, b: {:p}, t: {:p}", &(sf1.a), sf1.b, &(sf2.a) ) ;
717 }
718 ```
719
720 Pin 到栈上:
721
722 ```rust
723 use std::pin::Pin;
724 use std::marker::PhantomPinned;
725
726 #[derive(Debug)]
727 struct SelfReferential {
728 a: String,
729 b: *const String,
730 _marker: PhantomPinned,
731 }
732
733 impl SelfReferential {
734 fn new(txt: &str) -> Self {
735 Self {
736 a: String::from(txt),
737 b: std::ptr::null(),
738 _marker: PhantomPinned, // This makes our type `!Unpin`
739 }
740 }
741
742 fn init<'a>(self: Pin<&'a mut Self>) {
743 let self_ptr: *const String = &self.a;
744 let this = unsafe { self.get_unchecked_mut() };
745 this.b = self_ptr;
746 }
747
748 fn a<'a>(self: Pin<&'a Self>) -> &'a str {
749 &self.get_ref().a
750 }
751
752 fn b<'a>(self: Pin<&'a Self>) -> &'a String {
753 unsafe { &*(self.b) }
754 }
755 }
756
757 pub fn main() {
758 let mut sf1 = unsafe { Pin::new_unchecked(&mut SelfReferential::new("test1")) };
759 SelfReferential::init(sf1.as_mut());
760
761 let mut sf2 = unsafe { Pin::new_unchecked(&mut SelfReferential::new("test2")) };
762 SelfReferential::init(sf2.as_mut());
763
764 println!("a: {}, b: {}", SelfReferential::a(sf1.as_ref()), SelfReferential::b(sf1.as_ref()));
765 std::mem::swap(sf1.get_mut(), sf2.get_mut());
766 println!("a: {}, b: {}", SelfReferential::a(sf2.as_ref()), SelfReferential::b(sf2.as_ref()));
767 }
768
769 ```
770
771 一个 `Pin<&mut T>` 必须在被引用的T的整个生命周期被保持 pinned,这对于栈上的变量很难确认。
772 为了帮助处理这类问题,就有了像[pin-utils](https://docs.rs/pin-utils)这样的 crate。
773
774
775 栈上 vs 堆上:
776
777 ```rust
778 fn main(){
779
780 let s = "hello".to_string();
781 let p = s.as_str();
782 println!("{:p}", p);
783 println!("{:p}", s.as_ptr());
784 println!("{:p}", &s);
785 }
786 ```
787
788
789 Pin 到 堆上:
790
791 ```rust
792 use std::pin::Pin;
793 use std::marker::PhantomPinned;
794
795 #[derive(Debug)]
796 struct SelfReferential {
797 a: String,
798 b: *const String,
799 _marker: PhantomPinned,
800 }
801
802 impl SelfReferential {
803 fn new(txt: &str) -> Pin<Box<Self>> {
804 let t = Self {
805 a: String::from(txt),
806 b: std::ptr::null(),
807 _marker: PhantomPinned,
808 };
809 let mut boxed = Box::pin(t);
810 let self_ptr: *const String = &boxed.as_ref().a;
811 unsafe { boxed.as_mut().get_unchecked_mut().b = self_ptr };
812
813 boxed
814 }
815
816 fn a<'a>(self: Pin<&'a Self>) -> &'a str {
817 &self.get_ref().a
818 }
819
820 fn b<'a>(self: Pin<&'a Self>) -> &'a String {
821 unsafe { &*(self.b) }
822 }
823 }
824
825 pub fn main() {
826 let mut sf1 = SelfReferential::new("test1");
827 let mut sf2 = SelfReferential::new("test2");
828
829 println!("a: {}, b: {}",sf1.as_ref().a(), sf1.as_ref().b());
830 std::mem::swap(sf1.get_mut(), sf1.get_mut());
831 // std::mem::swap(&mut *sf1, &mut *sf2);
832 println!("a: {}, b: {}",sf2.as_ref().a(), sf2.as_ref().b());
833 }
834
835 ```
836
837 另外一个示例:
838
839 ```rust
840 use std::mem;
841 use std::marker::PhantomPinned;
842 use std::pin::Pin;
843
844 struct SelfReferential {
845 self_ptr: *const Self,
846 _pin: PhantomPinned,
847 }
848
849 fn main() {
850 let mut heap_value = Box::pin(SelfReferential {
851 self_ptr: 0 as *const _,
852 _pin: PhantomPinned,
853 });
854 let ptr = &*heap_value as *const SelfReferential;
855
856 // 这是安全的,因为修改结构体字段不会让结构体发生move
857 unsafe {
858 let mut_ref = Pin::as_mut(&mut heap_value);
859 Pin::get_unchecked_mut(mut_ref).self_ptr = ptr;
860 }
861
862 println!("heap value at: {:p}", heap_value);
863 println!("internal reference: {:p}", heap_value.self_ptr);
864
865 // 有效阻止了下面风险代码的发生
866
867 let stack_value = mem::replace(&mut *heap_value, SelfReferential {
868 self_ptr: 0 as *const _,
869 _pin: PhantomPinned,
870 });
871 println!("value at: {:p}", &stack_value);
872 println!("internal reference: {:p}", stack_value.self_ptr);
873 }
874
875
876
877
878 ```
879
880 ### 异步实现细节:Pin 与 UnPin
881
882 async/await 的要支持引用,就必须支持自引用结构。
883
884 Rust 源码内部:[https://github.com/rust-lang/rust/blob/master/library/core/src/future/mod.rs](https://github.com/rust-lang/rust/blob/master/library/core/src/future/mod.rs)
885
886 ```rust
887 // From Generator to Future
888 pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
889 where
890 T: Generator<ResumeTy, Yield = ()>,
891 {
892 #[rustc_diagnostic_item = "gen_future"]
893 struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
894
895 // 依赖这样一个重要事实:
896 // 即 async/await Future 是不可移动的,以便在基础生成器中创建自引用借用。
897 impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
898
899 impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
900 type Output = T::Return;
901 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
902 // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
903 let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
904
905 // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
906 // `.await` lowering will safely cast that back to a `&mut Context`.
907 // resume 里传递上下文指针
908 match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
909 GeneratorState::Yielded(()) => Poll::Pending,
910 GeneratorState::Complete(x) => Poll::Ready(x),
911 }
912 }
913 }
914
915 GenFuture(gen)
916 }
917
918 ```
919
920 Pin 利用类型系统避免 `&mut T` 被拿到,达到 固定 引用/指针 的目的。
921
922 [https://doc.rust-lang.org/std/pin/index.html](https://doc.rust-lang.org/std/pin/index.html)
923
924 - [pin-project-lite](https://crates.io/crates/pin-project-lite)
925
926
927 ### Pin 与 Unpin 属性
928
929 来自:[Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/04_pinning/01_chapter.html)
930
931 - 如果 `T: Unpin`(默认会实现),那么 `Pin<'a, T>` 完全等价于 `&'a mut T`。换言之: `Unpin` 意味着这个类型被移走也没关系,就算已经被固定了,所以 `Pin` 对这样的类型毫无影响。
932
933 - 如果 `T: !Unpin`, 获取已经被固定的 `T` 类型示例的 `&mut T`需要 `unsafe`。
934
935 - 标准库中的大部分类型实现 `Unpin`,在 Rust 中遇到的多数普通类型也是一样。但是, `async/await` 生成的 `Future` 是个例外。
936
937 - 你可以在 nightly 通过特性标记来给类型添加 `!Unpin` 约束,或者在 stable 给你的类型加 `std::marker::PhatomPinned` 字段。
938
939 - 你可以将数据固定到栈上或堆上
940
941 - 固定 `!Unpin` 对象到栈上需要 `unsafe`
942
943 - 固定 `!Unpin` 对象到堆上不需要` unsafe`。`Box::pin`可以快速完成这种固定。
944
945 - 对于 `T: !Unpin` 的被固定数据,你必须维护好数据内存不会无效的约定,或者叫 固定时起直到释放。这是 固定约定 中的重要部分。
946
947
948 ### Pin 用法约定
949
950 - 带 Pin 结构化包装的 投影 (`structural Pin projection`) : `Pin<&mut Wrapper<Field>> -> Pin<&mut Field>`。 `pin_utils::unsafe_pinned!` 宏可以做。
951 - 当结构体所有的字段都实现 Unpin ,整个结构体才可以实现 Unpin。(不允许任何实现使用不安全的方式将此类字段移出,比如 `Option::take` 是被禁止的)
952 - 结构体不能用 `#[repr(packed)]`
953 - 如果`Drop::drop`不移动任何字段,则整个结构只能实现`Drop`
954 - 不带 Pin 结构化包装的 投影 (`no structural Pin projection`) : `Pin<&mut Wrapper<Field>> -> &mut Field`。 ` pin_utils::unsafe_unpinned! ` 宏可以做的。
955
956 参考: [futures-util::future::map](https://github.com/rust-lang/futures-rs/blob/0.3.0-alpha.15/futures-util/src/future/map.rs#L14)
957
958 ```rust
959 impl<Fut, F> Map<Fut, F> {
960 unsafe_pinned!(future: Fut); // pin projection -----+
961 unsafe_unpinned!(f: Option<F>); // not pinned --+ |
962 // | |
963 // ... | |
964 // | |
965 fn poll (mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
966 // | |
967 match self.as_mut().future().poll(cx) { // <----+ required here
968 Poll::Pending => Poll::Pending, // |
969 Poll::Ready(output) => { // |
970 let f = self.f().take() // <--------+ allows this
971
972 ```
973
974*/
975pub fn f_pin_unpin() {}
976
977/**
978
979 # `no-std` 下的异步
980
981 - [futures-micro](https://github.com/irrustible/futures-micro)
982 - [embassy](https://github.com/embassy-rs/embassy)
983 - [executor for no-std](https://github.com/richardanaya/executor)
984
985*/
986pub fn no_std_async() {}
987
988/**
989 # 一个异步缓存代码实现源码导读 :[retainer](https://github.com/ChaosStudyGroup/retainer)
990
991*/
992pub fn async_cache_demo() {}