fast_steal/
lib.rs

1#![no_std]
2//! # fast-steal 神偷
3//!
4//! [![GitHub last commit](https://img.shields.io/github/last-commit/fast-down/core/stable)](https://github.com/fast-down/core/commits/stable)
5//! [![Test](https://github.com/fast-down/core/workflows/Test/badge.svg)](https://github.com/fast-down/core/actions)
6//! [![Latest version](https://img.shields.io/crates/v/fast-steal.svg)](https://crates.io/crates/fast-steal)
7//! [![Documentation](https://docs.rs/fast-steal/badge.svg)](https://docs.rs/fast-steal)
8//! [![License](https://img.shields.io/crates/l/fast-steal.svg)](https://github.com/fast-down/core/blob/stable/crates/fast-steal/LICENSE)
9//!
10//! `fast-steal` 是一个特别快的多线程库,支持超细颗粒度的任务窃取。
11//!
12//! ## 优势
13//!
14//! 1. no_std 支持,不依赖于标准库
15//! 2. 超细颗粒度任务窃取,速度非常快
16//! 3. 安全的 Rust,库中没有使用任何 unsafe 的代码
17//! 4. 测试完全覆盖,保证库的稳定性和可靠性
18//!
19//! ```rust
20//! use fast_steal::{Executor, Handle, Task, TaskList};
21//! use std::{collections::HashMap, sync::Arc, num::NonZero};
22//! use tokio::{
23//!     sync::{Mutex, mpsc},
24//!     task::{AbortHandle, JoinHandle},
25//! };
26//!
27//! pub struct TokioExecutor {
28//!     tx: mpsc::UnboundedSender<(u64, u64)>,
29//! }
30//! #[derive(Clone)]
31//! pub struct TokioHandle(Arc<Mutex<Option<JoinHandle<()>>>>, AbortHandle);
32//!
33//! impl Handle for TokioHandle {
34//!     type Output = ();
35//!     fn abort(&mut self) -> Self::Output {
36//!         self.1.abort();
37//!     }
38//! }
39//!
40//! impl Executor for TokioExecutor {
41//!     type Handle = TokioHandle;
42//!     fn execute(self: Arc<Self>, task: Arc<Task>, task_list: Arc<TaskList<Self>>) -> Self::Handle {
43//!         println!("execute");
44//!         let handle = tokio::spawn(async move {
45//!             loop {
46//!                 while task.start() < task.end() {
47//!                     let i = task.start();
48//!                     task.fetch_add_start(1);
49//!                     let res = fib(i);
50//!                     println!("task: {i} = {res}");
51//!                     self.tx.send((i, res)).unwrap();
52//!                 }
53//!                 if !task_list.steal(&task, NonZero::new(1).unwrap()) {
54//!                     break;
55//!                 }
56//!             }
57//!             assert_eq!(task_list.remove(&task), 1);
58//!         });
59//!         let abort_handle = handle.abort_handle();
60//!         TokioHandle(Arc::new(Mutex::new(Some(handle))), abort_handle)
61//!     }
62//! }
63//!
64//! fn fib(n: u64) -> u64 {
65//!     match n {
66//!         0 => 0,
67//!         1 => 1,
68//!         _ => fib(n - 1) + fib(n - 2),
69//!     }
70//! }
71//! fn fib_fast(n: u64) -> u64 {
72//!     let mut a = 0;
73//!     let mut b = 1;
74//!     for _ in 0..n {
75//!         (a, b) = (b, a + b);
76//!     }
77//!     a
78//! }
79//!
80//! #[tokio::main]
81//! async fn main() {
82//!     let (tx, mut rx) = mpsc::unbounded_channel();
83//!     let executor = Arc::new(TokioExecutor { tx });
84//!     let pre_data = [1..20, 41..48];
85//!     let task_list = Arc::new(TaskList::run(&pre_data[..], executor));
86//!     task_list
87//!         .clone()
88//!         .set_threads(NonZero::new(8).unwrap(), NonZero::new(1).unwrap());
89//!     let handles: Arc<[_]> = task_list.handles(|it| it.map(|h| h.clone()).collect());
90//!     drop(task_list);
91//!     for handle in handles.iter() {
92//!         handle.0.lock().await.take().unwrap().await.unwrap();
93//!     }
94//!     let mut data = HashMap::new();
95//!     while let Some((i, res)) = rx.recv().await {
96//!         println!("main: {i} = {res}");
97//!         if data.insert(i, res).is_some() {
98//!             panic!("数字 {i},值为 {res} 重复计算");
99//!         }
100//!     }
101//!     dbg!(&data);
102//!     for range in pre_data {
103//!         for i in range {
104//!             assert_eq!((i, data.get(&i)), (i, Some(&fib_fast(i))));
105//!             data.remove(&i);
106//!         }
107//!     }
108//!     assert_eq!(data.len(), 0);
109//! }
110//! ```
111
112mod executor;
113mod task;
114mod task_list;
115
116pub use executor::{Executor, Handle};
117pub use task::Task;
118pub use task_list::TaskList;