diff --git a/README.md b/README.md index 49b496cf24e55b485bab6c6a9b1d3afd7b54f76a..29d59973da8002ae5876a13584d292e1126a6ebf 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,23 @@ Rust asynchronous runtime, provides functionalities such as spawning async tasks, async io, synchronization, parallel calculation. ### Overall structure -![structure](./figure/structure.png) +![structure](./figures/structure.png) +### Crates inner relations +![inner_dependencies](./figures/inner_dependencies.png) + +ylong_runtime depends on the other three crates. +- ylong_io: provides event-driven net io, using epoll or iocp to achieve non-blocking tcp or udp +- ylong_ffrt: provides function flow runtime APIs. It serves as an alternative scheduler for ylong_runtime. +- ylong_macros: provides procedural macros for `select!` and ``main``/``test``. ## Compile Build Method 1: Introduce ylong_runtime in Cargo.toml ```toml -#[dependence] -ylong_runtime = { git = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime.git", version = "1.9.0", features = ["full"]} +#[dependencies] +ylong_runtime = { git = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime.git", features = ["full"]} ``` For compiling FFRT version of ylong_runtime, rename ``ylong_ffrt/build_ffrt.rs`` to ``ylong_ffrt/build.rs``, and export `LD_LIBRARY_PATH` @@ -27,6 +34,8 @@ deps += ["//commonlibrary/rust/ylong_runtime/ylong_runtime:lib"] ## directory ``` ylong_runtime +|── docs # User guide +|── figures # Structure figures in docspo |── ylong_ffrt | └── src # FFRT rust ffi |── ylong_io diff --git a/README_zh.md b/README_zh.md index 002b47dc10e22d3e78320c2211c029760fd70984..50cb8934bbd74a069bdb356ed3249fac4dbf2790 100644 --- a/README_zh.md +++ b/README_zh.md @@ -1,14 +1,24 @@ # ylong_runtime ## 简介 -Rust异步运行时库,用于生成并执行异步任务。主要分为Time, Sync, Parallel calculation, IO四个模块。 +Rust异步运行时库,用于生成并执行异步任务。同时提供了异步网络IO,异步文件IO,定时器,同步原语,并行迭代器等功能。 ### 图一 整体架构图 -![structure](./figure/structure.png) +![structure](./figures/structure.png) + +### 图二 模块间关系 +![inner_dependencies](./figures/inner_dependencies.png) + +ylong_runtime 依赖以下三个库 +- ylong_io: 提供了事件驱动型网络IO,通过epoll或iocp实现了非阻塞性的tcp和udp。 +- ylong_ffrt: 提供了Function Flow Runtime的接口,可作为ylong_runtime的底层调度器。 +- ylong_macros: 提供了ylong_runtime所需的过程宏功能,用于`select!`功能, 以及`main`/`test`。 ## 目录 ``` ylong_runtime +|── docs # 使用文档 +|── figures # 架构图 |── ylong_ffrt | └── src # FFRT ffi封装 |── ylong_io @@ -49,8 +59,8 @@ ylong_runtime 方法一:在Cargo.toml中引入ylong_runtime ```toml -#[dependence] -ylong_runtime = { git = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime.git", version = "1.9.0", features = ["full"]} +#[dependencies] +ylong_runtime = { git = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime.git", features = ["full"]} ``` 如果需要编译ffrt版本,将ylong_ffrt目录下的``build_ffrt.rs``文件重命名为``build.rs``, 并设置`LD_LIBRARY_PATH` diff --git a/figure/structure.png b/figure/structure.png deleted file mode 100644 index 6a396e5bedeab83834ea7116da40c9e2c4eb822b..0000000000000000000000000000000000000000 Binary files a/figure/structure.png and /dev/null differ diff --git a/figures/inner_dependencies.png b/figures/inner_dependencies.png new file mode 100644 index 0000000000000000000000000000000000000000..c0503d1289cdb90970489f50c72cecc13afd22a7 Binary files /dev/null and b/figures/inner_dependencies.png differ diff --git a/figures/structure.png b/figures/structure.png new file mode 100644 index 0000000000000000000000000000000000000000..1234e3c41369ac4d2b63d5a091e0e40057050b14 Binary files /dev/null and b/figures/structure.png differ diff --git a/ylong_ffrt/Cargo.toml b/ylong_ffrt/Cargo.toml index b31554b2f39fb93e86a5333c2efdf583b39d1a00..4150625c1b96e6d5461ffa1c70b49f1635c01629 100644 --- a/ylong_ffrt/Cargo.toml +++ b/ylong_ffrt/Cargo.toml @@ -1,12 +1,10 @@ [package] name = "ylong_ffrt" -version = "0.1.0" -authors = ["f00567414 "] +version = "1.0.0" edition = "2021" -description = "Runtime Environment" +description = "FFRT adapter" license = "Apache-2.0" -readme = "README.md" -repository = "https://open.codehub.huawei.com/innersource/Ylong_Rust/ylong_rs/files?ref=ylong_oh&filePath=src%2Fruntime%2Fylong_ffrt" +repository = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime" keywords = ["ylong", "ffrt"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/ylong_io/Cargo.toml b/ylong_io/Cargo.toml index 2b9424faa7d50f0725113a8843eafeeb30bd44d0..0ca5bc5875e29c35d775955850fbeaf2056ff9b5 100644 --- a/ylong_io/Cargo.toml +++ b/ylong_io/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "ylong_io" -version = "0.1.0" -edition = "2018" -description = "IO module of YLong" -readme = "README.md" +version = "1.0.0" +edition = "2021" +description = "Event Driven IO" license = "Apache-2.0" -repository = "https://open.codehub.huawei.com/innersource/Ylong_Rust/ylong_rs/files?ref=master&filePath=src%2Fschedule%2Fylong_io" +repository = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime" keywords = ["ylong", "io", "epoll"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/ylong_io/README.md b/ylong_io/README.md deleted file mode 100644 index ea633dbca078c3d2c6224eb3fe2890c1b2d41cc2..0000000000000000000000000000000000000000 --- a/ylong_io/README.md +++ /dev/null @@ -1,78 +0,0 @@ -## ylong_io 介绍 -提供通信 io 功能,底层实现使用 epoll。 - -### 功能介绍 -- 支持 tcp 协议: - - 支持使用 tcp 协议进行通信,并使用 epoll 进行异步 io。 - -### 使用实例 -TCP 通信实例 - -``` -use std::collections::HashMap; -use std::io; -use std::io::{Read, Write}; -use ylong_io::{EventTrait, Events, Interest, Poll, TcpListener, Token}; - -// 唯一标识 SEVER 的 Token -const SERVER: Token = Token(0); - -fn main() -> io::Result<()> { - // 创建 Poll 实例,用于 epoll 查找事件。 - let poll = Poll::new()?; - - // 设置本地地址,并 bind 本地端口,得到 fd。 - let addr = "127.0.0.1:1234".parse().unwrap(); - let mut server = TcpListener::bind(addr)?; - - // 将 server 的 fd 注册到 epoll 中进行监听,监听可读事件。 - poll.register(&mut server, SERVER, Interest::READABLE)?; - let mut events = Events::with_capacity(128); - - // 保存远端传来的链接。 - let mut connections = HashMap::new(); - // 远端传来的 socket fd 用从 1 开始的计数标号。 - let mut unique_token = Token(SERVER.0 + 1); - - // 事件循环 - loop { - // 检查是否有事件到来。 - poll.poll(&mut events, None)?; - - for event in events.iter() { - // server 有事件到来,说明远端有新连接到来。 - if SERVER == event.token() { - let (mut stream, addr) = server.accept()?; - - // 设置Token。 - let token = Token(unique_token.0 + 1); - unique_token = Token(unique_token.0 + 1); - // 注册到 epoll 中监听。 - poll.register( - &mut stream, - token, - Interest::READABLE.add(Interest::WRITABLE), - )?; - // 添加到数据结构中进行保存。 - connections.insert(token, stream); - } else { - // 通过唯一标识查找连接。 - match connections.get_mut(&event.token()) { - //... 执行通信相关的逻辑 - } - None => break, - } - } - } - } -} - - ``` - -### 如何使用 -在 Cargo.toml 文件中添加 dependencies 即可 -``` -[dependencies] -ylong_io = "0.1.0" -``` \ No newline at end of file diff --git a/ylong_runtime/Cargo.toml b/ylong_runtime/Cargo.toml index d69b5aad60b53e0a0243d1c77911d9ab29332f1f..ec3cac2d78812e4d9ea3fa859b56fc1cdaab2a8c 100644 --- a/ylong_runtime/Cargo.toml +++ b/ylong_runtime/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "ylong_runtime" -version = "1.9.0" -edition = "2018" +version = "1.0.0" +edition = "2021" description = "Runtime Environment" license = "Apache-2.0" -readme = "README.md" -repository = "https://open.codehub.huawei.com/innersource/Ylong_Rust/ylong_rs/files?ref=master&filePath=src%2Fschedule%2Fylong_runtime" +repository = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime" keywords = ["ylong", "runtime", "executor"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/ylong_runtime/README.md b/ylong_runtime/README.md deleted file mode 100644 index ef6414e51ebae4442d30a20f250a8829aebe6ecf..0000000000000000000000000000000000000000 --- a/ylong_runtime/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# ylong_runtime - -## Introduction -Rust language doesn't provide an asynchronous runtime. Instead, it provides basic primitives and functionalities such as ``async``, ``await``, ``Future``, and ``Waker``. Therefore, it's users' responsibilities to implement the runtime, or choose from an existing third party's runtime. - -## Compile Build - -1. Introduce ylong_runtime in Cargo.toml - -```toml -#[dependence] -ylong_runtime = { git = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime.git", version = "1.9.0", features = ["full"]} -``` - -2. Add dependencies to BUILD.gn where appropriate - -``` -deps += ["//commonlibrary/rust/ylong_runtime/ylong_runtime:ylong_runtime"] -``` - - - -## Usage - -### `ylong` global thread pool -```rust -use std::net::{Ipv4Addr, SocketAddrV4}; -use ylong_runtime::io::*; -use ylong_runtime::net::TcpListener; -fn main() -> std::io::Result<()> { - ylong_runtime::block_on(async { - let ip = Ipv4Addr::new(127, 0, 0, 1); - let addr = SocketAddrV4::new(ip, 8080); - let listener = TcpListener::bind(addr.into()).await?; - loop { - let (mut stream, _) = listener.accept().await?; - stream.write_all("hello ylong".as_bytes()); - } - }) -} -``` - - -#### Thread pool settings - -Users can set the config of the runtime, which must be set before `block_on` and `spawn`, otherwise `runtime` will use the default configuration. - -```rust -fn main() { - let _ = ylong_runtime::builder::RuntimeBuilder::new_multi_thread() - .worker_stack_size(10) - .keep_alive_time(std::time::Duration::from_secs(10)) - .build_global(); - - let fut = async { - - }; - let _ = ylong_runtime::block_on(fut); -} -``` - -### `ylong` scheduling framework non-asynchronous thread pool (spawn_blocking) - -```rust -fn main() { - let fut = async { - // It could be a closure or function. - let join_handle = runtime.spawn_blocking(|| {}); - // Waits the task until finished. - let _result = join_handle.await; - }; - let _ = ylong_runtime::block_on(fut); -} -``` - - -### ParIter Introduction - -ParIter and its related interfaces are defined in the module `ylong_runtime::iter`. `ParIter` supports parallel iterations over threads, where a set of data is split and the split data performs the operations in the iterator in parallel over the threads. - -```rust -use ylong_runtime::iter::prelude::*; - -fn main() { - ylong_runtime::block_on(fut()); -} - -async fn fut() { - let v = (1..30).into_iter().collect::>(); - let sum = v.par_iter().map(|x| fibbo(*x)).sum().await.unwrap(); - println!("{}", sum); -} - -fn fibbo(i: usize) -> usize { - match i { - 0 => 1, - 1 => 1, - n => fibbo(n - 1) + fibbo(n - 2), - } -} -``` - -## Acknowledgements - -Based on the user's habit, the API of this library, after changing the original Rust standard library synchronous interface implementation to asynchronous, retains the original naming style of the standard library, such as``TcpStream::connect``, ``File::read``, ``File::write`` and so on. We also refer to some of Tokio's general API design ideas, and we would like to express our gratitude to the Rust standard library and Tokio \ No newline at end of file diff --git a/ylong_runtime/README_zh.md b/ylong_runtime/README_zh.md deleted file mode 100644 index 03deb83c8cdcd2c66af5c8ac8ce76042d115fff7..0000000000000000000000000000000000000000 --- a/ylong_runtime/README_zh.md +++ /dev/null @@ -1,110 +0,0 @@ -# ylong_runtime - -## 简介 -Rust语言在提供了``async``/``await``, ``Future``, ``Waker``等异步基础组件的同时,并不提供具体的异步运行时实现。而具体实现则需要用户自己构建,或者使用社区已构建好的异步运行时。这样的好处是用户可以在自己的使用场景做定制化的优化。 - -## 编译构建 - -1. 在Cargo.toml中引入ylong_runtime - -```toml -#[dependence] -ylong_runtime = { git = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime.git", version = "1.9.0", features = ["full"]} -``` - -2. 在 BUILD.gn 合适的地方添加依赖 - -``` -deps += ["//commonlibrary/rust/ylong_runtime/ylong_runtime:ylong_runtime"] -``` - -## 使用说明 - -### `ylong` 全局线程池 - -```rust -use std::net::{Ipv4Addr, SocketAddrV4}; -use ylong_runtime::io::*; -use ylong_runtime::net::TcpListener; -fn main() -> std::io::Result<()> { - ylong_runtime::block_on(async { - let ip = Ipv4Addr::new(127, 0, 0, 1); - let addr = SocketAddrV4::new(ip, 8080); - let listener = TcpListener::bind(addr.into()).await?; - loop { - let (mut stream, _) = listener.accept().await?; - stream.write_all("hello ylong".as_bytes()); - } - }) -} - -``` - -#### 线程池设置 - -可以链式设置runtime的具体配置。必须在`block_on`,`spawn`之前设置,否则`runtime`会使用默认配置。 - -```rust -fn main() { - let _ = ylong_runtime::builder::RuntimeBuilder::new_multi_thread() - .worker_stack_size(10) - .keep_alive_time(std::time::Duration::from_secs(10)) - .build_global(); - - let fut = async { - - }; - let _ = ylong_runtime::block_on(fut); -} -``` - - - -### `ylong` 调度框架非异步线程池(spawn_blocking)使用 - -```rust -fn main() { - let fut = async { - // 这里可以是闭包也可以是函数。 - let join_handle = ylong_runtime::spawn_blocking(|| {}); - // 等待任务执行完成 - let _result = join_handle.await; - }; - let _ = ylong_runtime::block_on(fut); -} - -``` - - - -### ParIter 功能介绍 - -`ParIter` 及其相关接口定义于模块 `ylong_runtime::iter`,`ParIter`支持数据在线程中做并行迭代,一组数据会在线程中被分割,分割后的数据会在线程中并行执行迭代器中的操作。 - -```rust -use ylong_runtime::iter::prelude::*; - -fn main() { - ylong_runtime::block_on(fut()); -} - -async fn fut() { - let v = (1..30).into_iter().collect::>(); - let sum = v.par_iter().map(|x| fibbo(*x)).sum().await.unwrap(); - println!("{}", sum); -} - -fn fibbo(i: usize) -> usize { - match i { - 0 => 1, - 1 => 1, - n => fibbo(n - 1) + fibbo(n - 2), - } -} -``` - - - -## 致谢 - -基于用户的使用习惯,本库的API在将原本Rust标准库同步的接口实现改为异步后,保留了标准库原本的命名风格,如``TcpStream::connect``、``File::read``、``File::write``等。同时也参考了Tokio的部分通用API设计思想,在此对Rust标准库和Tokio表示感谢 \ No newline at end of file diff --git a/ylong_runtime_macros/Cargo.toml b/ylong_runtime_macros/Cargo.toml index 0e21724b217dba67ae8de83ac8541a36985af13d..cf939186b546d3f9da7019ee2e8953b831989351 100644 --- a/ylong_runtime_macros/Cargo.toml +++ b/ylong_runtime_macros/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "ylong_runtime_macros" -version = "1.11.0" +version = "1.0.0" edition = "2021" description = "Ylong_runtime Procedure Macro" license = "Apache-2.0" -readme = "README.md" -repository = "https://open.codehub.huawei.com/innersource/Ylong_Rust/ylong_rs/files?ref=master&filePath=src%2Fschedule%2Fylong_runtime_macro" +repository = "https://gitee.com/openharmony-sig/commonlibrary_rust_ylong_runtime" keywords = ["Ylong", "Runtime", "Procedure", "Macro"] [lib] diff --git a/ylong_runtime_macros/README_en.md b/ylong_runtime_macros/README_en.md deleted file mode 100644 index ab28f53d9d27c62e1b2f7b97f7d66b4f15c5eae3..0000000000000000000000000000000000000000 --- a/ylong_runtime_macros/README_en.md +++ /dev/null @@ -1,127 +0,0 @@ -## Ylong_macro Process Macros - -#### Currently, only the internal implementation macro of the select! macro is contained. - -#### Do not use directly - -### select! Macro Usage Examples - -Basic select with two branches. - -``` - async fn do_async1() { - // do task - } - async fn do_async2() { - // do task - } - async fn select_test() { - ylong_runtime::select! { - _ = do_async1() => { - println!("do_async1() completed first"); - }, - _ = do_async2() => { - println!("do_async2() completed first"); - } - } - } -``` -Uses if to filter asynchronous tasks -``` - async fn do_async1() -> i32 { - 1 - } - async fn do_async2() -> i32 { - 2 - } - async fn do_async3() -> bool { - false - } - async fn select_test() { - let mut count = 0; - ylong_runtime::select! { - a = do_async1(), if false => { - count += a; - println!("do_async1() completed first{:?}", a); - }, - b = do_async2() => { - count += b; - println!("do_async2() completed first{:?}", b); - }, - c = do_async3(), if false => { - if c { - println!("do_async3() completed true"); - } - else { - println!("do_async3() completed false"); - } - } - } - assert_eq!(count, 2); - } - ``` -Repeated uses select! until all task return. - ``` - #[cfg(feature = "sync")] - async fn select_channel() { - let (tx1, mut rx1) = ylong_runtime::sync::oneshot::channel(); - let (tx2, mut rx2) = ylong_runtime::sync::oneshot::channel(); - - ylong_runtime::spawn(async move { - tx1.send("first").unwrap(); - }); - - ylong_runtime::spawn(async move { - tx2.send("second").unwrap(); - }); - - let mut a = None; - let mut b = None; - - while a.is_none() || b.is_none() { - ylong_runtime::select! { - v1 = (&mut rx1), if a.is_none() => a = Some(v1.unwrap()), - v2 = (&mut rx2), if b.is_none() => b = Some(v2.unwrap()), - } - } - - let res = (a.unwrap(), b.unwrap()); - - assert_eq!(res.0, "first"); - assert_eq!(res.1, "second"); - } - ``` -Uses 'biased' to execute four task in the specified sequence. - ``` - async fn select_biased() { - let mut count = 0u8; - - loop { - ylong_runtime::select! { - biased; - _ = async {}, if count < 1 => { - count += 1; - assert_eq!(count, 1); - } - _ = async {}, if count < 2 => { - count += 1; - assert_eq!(count, 2); - } - _ = async {}, if count < 3 => { - count += 1; - assert_eq!(count, 3); - } - _ = async {}, if count < 4 => { - count += 1; - assert_eq!(count, 4); - } - else => { - break; - } - } - } - - assert_eq!(count, 4); - } - ``` -### Subsequent plans to add process macros: Main \ No newline at end of file