1# ylong_runtime 用户指南
2
3ylong_runtime提供了异步任务生成以及调度的能力,同时异步化了各类系统IO,并提供了同步原语,定时器功能。
4
5ylong_runtime 整体分为4个库:
6
7- ylong_ffrt: Function Flow Runtime的FFI层
8- ylong_io: 事件驱动型网络IO库
9- ylong_runtime: 异步调度框架库
10- ylong_runtime_macros:调度框架宏库
11
12其中 ylong_runtime 承载了异步调度框架的主体功能,并且依赖其余三个库提供的底层能力。
13
14如果需要查看详细的接口说明请查看对应接口的 docs,可以使用 `cargo doc --open` 生成并查看 docs。
15
16## 配置异步调度框架
17
18可以链式设置runtime的具体配置。必须在`block_on`,`spawn`之前设置,否则`runtime`会使用默认配置。 相关接口位于`ylong_runtime::builder`.
19
20```rust
21fn main() {
22    let _ = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
23        .worker_stack_size(10)
24        .keep_alive_time(std::time::Duration::from_secs(10))
25        .build_global();
26
27    let fut = async {
28
29    };
30    let _ = ylong_runtime::block_on(fut);
31}
32```
33
34## 生成异步任务
35
36通过``spawn``生成异步任务
37
38```rust
39fn main() {
40    let handle = ylong_runtime::spawn(async move {
41        // 嵌套生成异步任务
42        let handle = ylong_runtime::spawn(async move {
43            1
44        });
45
46        // 在异步上下文使用await异步等待任务完成
47        let res = handle.await.unwrap();
48        assert_eq!(res, 1);
49        1
50    });
51    // 在同步上下文使用block_on阻塞等待异步任务完成
52    let res = ylong_runtime::block_on(handle).unwrap();
53    assert_eq!(res, 1);
54}
55
56```
57
58## 生成非异步任务
59
60通过``spawn_blocking``生成任务
61
62```rust
63fn main() {
64    let fut = async {
65        // 这里可以是闭包也可以是函数。
66        let join_handle = ylong_runtime::spawn_blocking(|| {});
67        // 等待任务执行完成
68        let _result = join_handle.await;
69    };
70    let _ = ylong_runtime::block_on(fut);
71}
72
73```
74
75## 取消异步任务
76
77通过``join_handle``的``cancel``接口取消任务。如果任务成功取消,等待该任务将立即返回一个错误。
78
79```rust
80use std::time::Duration;
81use ylong_runtime::error::ErrorKind;
82use ylong_runtime::time::sleep;
83
84fn main() {
85    let handle = ylong_runtime::spawn(async move {
86        let task = ylong_runtime::spawn(async move {
87            sleep(Duration::from_secs(100)).await;
88        });
89        task.cancel();
90        let res = task.await.err().unwrap();
91        assert_eq!(res.kind(), ErrorKind::TaskCanceled);
92    });
93    ylong_runtime::block_on(handle).unwrap();
94}
95```
96
97## 使用网络异步IO
98
99使用 ylong_runtime 中封装的异步IO(TCP/UDP)进行网络连接,相关接口定义位于模块 `ylong_runtime::net`.
100
101```rust
102use ylong_runtime::net::{TcpListener, TcpStream};
103use ylong_runtime::io::AsyncWrite;
104
105fn main() {
106    let addr = "127.0.0.1:8081".parse().unwrap();
107    let handle = ylong_runtime::spawn(async move {
108        // 异步TCP服务端,监听一个端口
109        let listener = TcpListener::bind(addr).await;
110        if let Err(e) = listener {
111            assert_eq!(0, 1, "Bind Listener Failed {e}");
112        }
113
114        let listener = listener.unwrap();
115        // 接受一个TCP连接请求
116        let mut socket = match listener.accept().await {
117            Ok((socket, _)) => socket,
118            Err(e) => {
119                assert_eq!(0, 1, "Bind accept Failed {e}");
120            }
121        };
122
123        // 发送一条信息给客户端
124        if let Err(e) = socket.write(b"hello client").await {
125            assert_eq!(0, 1, "failed to write to socket {e}");
126        }
127    });
128}
129
130```
131
132## 使用定时器
133定时器相关接口位于模块`ylong_runtime::time`. 里面包括了任务睡眠,任务超时,以及周期性定时器的功能。
134
135```rust
136use std::time::Duration;
137use ylong_runtime::time::{timeout, sleep};
138
139fn main() {
140    let handle = ylong_runtime::spawn(async move {
141        // 这个任务将在100微秒后超时,任务在这个时间内完成将返回结果。
142        let result = timeout(Duration::from_millis(100), async { 1 }).await;
143        assert_eq!(result.unwrap(), 1);
144
145        // 如果任务超时,将返回一个超时错误。
146        let result = timeout(Duration::from_millis(100), sleep(Duration::from_secs(1)));
147        assert!(result.is_err());
148    });
149}
150
151
152```
153
154## 使用ParIter
155
156`ParIter` 及其相关接口定义于模块 `ylong_runtime::iter`,`ParIter`支持数据在线程中做并行迭代,一组数据会在线程中被分割,分割后的数据会在线程中并行执行迭代器中的操作。
157
158```rust
159use ylong_runtime::iter::prelude::*;
160
161fn main() {
162    ylong_runtime::block_on(fut());
163}
164
165async fn fut() {
166    let v = (1..30).into_iter().collect::<Vec<usize>>();
167    let sum = v.par_iter().map(|x| fibbo(*x)).sum().await.unwrap();
168    println!("{}", sum);
169}
170
171fn fibbo(i: usize) -> usize {
172    match i {
173        0 => 1,
174        1 => 1,
175        n => fibbo(n - 1) + fibbo(n - 2),
176    }
177}
178```