Skip to main content

selection_capture/
async_api.rs

1use crate::traits::{AppAdapter, AppProfileStore, CancelSignal, CapturePlatform};
2use crate::types::{CaptureOptions, CaptureOutcome};
3
4/// Async wrapper around [`crate::capture`].
5///
6/// On a **multi-thread** Tokio runtime this uses `block_in_place` to offload
7/// the blocking work to the current thread without stalling other tasks.
8///
9/// On a **current-thread** (`LocalSet`) runtime `block_in_place` is unavailable
10/// because there is only one worker thread. In that case the underlying sync
11/// call runs directly on the async task thread and will block the executor for
12/// its duration.  If you are using a current-thread runtime, call the
13/// synchronous [`crate::capture`] API from a `spawn_blocking` closure at the
14/// call site instead — that avoids blocking all other tasks on the runtime.
15pub async fn capture_async(
16    platform: &impl CapturePlatform,
17    store: &impl AppProfileStore,
18    cancel: &impl CancelSignal,
19    adapters: &[&dyn AppAdapter],
20    options: &CaptureOptions,
21) -> CaptureOutcome {
22    match tokio::runtime::Handle::try_current() {
23        Ok(handle) if handle.runtime_flavor() == tokio::runtime::RuntimeFlavor::MultiThread => {
24            tokio::task::block_in_place(|| {
25                crate::capture(platform, store, cancel, adapters, options)
26            })
27        }
28        // Current-thread or no-runtime path: run synchronously.
29        // NOTE: This blocks the executor thread for the duration of the capture.
30        // See the function-level doc comment for the recommended workaround.
31        Ok(_) | Err(_) => crate::capture(platform, store, cancel, adapters, options),
32    }
33}