1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*******************************************************************************
*
* Copyright (c) 2025 - 2026 Haixing Hu.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0.
*
******************************************************************************/
use Callable;
use crateTokioExecution;
use ;
/// Executes callable tasks on Tokio's blocking task pool.
///
/// `TokioExecutor` is a [`FutureExecutor`]: its [`Executor::call`] and
/// [`Executor::execute`] methods return a [`TokioExecution`] value that
/// **implements [`Future`]** with
/// [`Output`](std::future::Future::Output) `= Result<R, E>`. You
/// obtain the callable's result by **`.await`ing** (or polling) that future; it
/// is **not** a resolved [`Result`] at return time.
///
/// # Semantics
///
/// * **`call` schedules work immediately** — [`Executor::call`] runs
/// [`tokio::task::spawn_blocking`] **synchronously** before it returns. A
/// Tokio runtime must **already be active** on the current thread when `call`
/// runs (for example inside an `async` block executed under
/// [`Runtime::block_on`](tokio::runtime::Runtime::block_on) or
/// [`#[tokio::main]`](https://docs.rs/tokio/latest/tokio/attr.main.html)).
/// Calling `call` first and only then entering a runtime is wrong: the
/// blocking task was submitted with **no** runtime at `call` time.
/// * **Any normal Tokio entry point works** — you are **not** restricted to
/// [`Builder::new_current_thread`](tokio::runtime::Builder::new_current_thread);
/// a multi-thread [`Runtime`](tokio::runtime::Runtime) or an async handler in
/// a server is fine, as long as `call` happens while that runtime is running.
/// * **Await the returned future on Tokio** — the [`TokioExecution`] polls a
/// [`JoinHandle`](tokio::task::JoinHandle); complete it with `.await` inside
/// the same kind of Tokio-driven async context.
/// * **Blocking pool** — the closure runs on Tokio's *blocking* thread pool, not
/// on the core async worker threads, so heavy synchronous work does not
/// starve other async tasks on the runtime.
/// * **Compared to
/// [`ThreadPerTaskExecutor`](qubit_executor::executor::ThreadPerTaskExecutor)** —
/// this type **reuses** Tokio-managed blocking threads (bounded pool) instead
/// of one new [`std::thread`] per task, and you **await** the result instead
/// of calling a blocking [`TaskHandle::get`](qubit_executor::TaskHandle::get).
///
/// # Examples
///
/// The following uses a single-thread [`Runtime`](tokio::runtime::Runtime) only to keep the snippet
/// self-contained; [`#[tokio::main]`](https://docs.rs/tokio/latest/tokio/attr.main.html)
/// or a multi-thread runtime are equally valid.
///
/// ```rust
/// use std::io;
///
/// use qubit_tokio_executor::{
/// Executor,
/// TokioExecutor,
/// };
///
/// # fn main() -> io::Result<()> {
/// tokio::runtime::Builder::new_current_thread()
/// .enable_all()
/// .build()?
/// .block_on(async {
/// let executor = TokioExecutor;
/// let value = executor.call(|| Ok::<i32, io::Error>(40 + 2)).await?;
/// assert_eq!(value, 42);
/// Ok::<(), io::Error>(())
/// })?;
/// # Ok(())
/// # }
/// ```
;