fast_steal/lib.rs
1#![no_std]
2//! # fast-steal 神偷
3//!
4//! [](https://github.com/fast-down/core/commits/stable)
5//! [](https://github.com/fast-down/core/actions)
6//! [](https://crates.io/crates/fast-steal)
7//! [](https://docs.rs/fast-steal)
8//! [](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;