1 | use std::future::Future; |
2 | use std::panic::catch_unwind; |
3 | use std::thread; |
4 | |
5 | use async_executor::{Executor, Task}; |
6 | use async_io::block_on; |
7 | use async_lock::OnceCell; |
8 | use futures_lite::future; |
9 | |
10 | /// Spawns a task onto the global executor (single-threaded by default). |
11 | /// |
12 | /// There is a global executor that gets lazily initialized on first use. It is included in this |
13 | /// library for convenience when writing unit tests and small programs, but it is otherwise |
14 | /// more advisable to create your own [`Executor`]. |
15 | /// |
16 | /// By default, the global executor is run by a single background thread, but you can also |
17 | /// configure the number of threads by setting the `SMOL_THREADS` environment variable. |
18 | /// |
19 | /// # Examples |
20 | /// |
21 | /// ``` |
22 | /// let task = smol::spawn(async { |
23 | /// 1 + 2 |
24 | /// }); |
25 | /// |
26 | /// smol::block_on(async { |
27 | /// assert_eq!(task.await, 3); |
28 | /// }); |
29 | /// ``` |
30 | pub fn spawn<T: Send + 'static>(future: impl Future<Output = T> + Send + 'static) -> Task<T> { |
31 | static GLOBAL: OnceCell<Executor<'_>> = OnceCell::new(); |
32 | |
33 | fn global() -> &'static Executor<'static> { |
34 | GLOBAL.get_or_init_blocking(|| { |
35 | let num_threads = { |
36 | // Parse SMOL_THREADS or default to 1. |
37 | std::env::var("SMOL_THREADS" ) |
38 | .ok() |
39 | .and_then(|s| s.parse().ok()) |
40 | .unwrap_or(1) |
41 | }; |
42 | |
43 | for n in 1..=num_threads { |
44 | thread::Builder::new() |
45 | .name(format!("smol- {}" , n)) |
46 | .spawn(|| loop { |
47 | catch_unwind(|| block_on(global().run(future::pending::<()>()))).ok(); |
48 | }) |
49 | .expect("cannot spawn executor thread" ); |
50 | } |
51 | |
52 | // Prevent spawning another thread by running the process driver on this thread. |
53 | let ex = Executor::new(); |
54 | #[cfg (not(target_os = "espidf" ))] |
55 | ex.spawn(async_process::driver()).detach(); |
56 | ex |
57 | }) |
58 | } |
59 | |
60 | global().spawn(future) |
61 | } |
62 | |