vortex_io/runtime/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! A Vortex runtime provides an abstract way of scheduling mixed I/O and CPU workloads onto the
5//! various threading models supported by Vortex.
6//!
7//! In the future, it may also include a buffer manager or other shared resources.
8//!
9//! The threading models we currently support are:
10//! * Single-threaded: all work is driven on the current thread.
11//! * Multi-threaded: work is driven on a pool of threads managed by Vortex.
12//! * Worker Pool: work is driven on a pool of threads provided by the caller.
13//! * Tokio: work is driven on a Tokio runtime provided by the caller.
14//!
15
16use futures::future::BoxFuture;
17use futures::stream::BoxStream;
18
19use crate::file::{IoRequest, ReadSourceRef};
20
21mod blocking;
22pub use blocking::*;
23mod handle;
24pub use handle::*;
25
26#[cfg(not(target_arch = "wasm32"))]
27pub mod current;
28#[cfg(not(target_arch = "wasm32"))]
29mod pool;
30#[cfg(not(target_arch = "wasm32"))]
31pub mod single;
32#[cfg(not(target_arch = "wasm32"))]
33mod smol;
34#[cfg(feature = "tokio")]
35pub mod tokio;
36#[cfg(target_arch = "wasm32")]
37pub mod wasm;
38
39#[cfg(test)]
40mod tests;
41
42/// Trait used to abstract over different async runtimes.
43pub(crate) trait Executor: Send + Sync {
44    /// Spawns a future to be executed on the runtime.
45    ///
46    /// The future should continue to be polled in the background by the runtime.
47    /// The returned `AbortHandle` may be used to optimistically cancel the future.
48    fn spawn(&self, fut: BoxFuture<'static, ()>) -> AbortHandleRef;
49
50    /// Spawns a CPU-bound task for execution on the runtime.
51    ///
52    /// The returned `AbortHandle` may be used to optimistically cancel the task if it has not
53    /// yet started executing.
54    fn spawn_cpu(&self, task: Box<dyn FnOnce() + Send + 'static>) -> AbortHandleRef;
55
56    /// Spawns a blocking I/O task for execution on the runtime.
57    ///
58    /// The returned `AbortHandle` may be used to optimistically cancel the task if it has not
59    /// yet started executing.
60    fn spawn_blocking(&self, task: Box<dyn FnOnce() + Send + 'static>) -> AbortHandleRef;
61
62    /// Spawns an I/O task for execution on the runtime.
63    /// The runtime can choose to invoke the task's `Send` or `!Send` versions.
64    ///
65    /// Cancellation is implied by termination of the request stream.
66    fn spawn_io(&self, task: IoTask);
67}
68
69/// A handle that may be used to optimistically abort a spawned task.
70///
71/// If dropped, the task should continue to completion.
72/// If explicitly aborted, the task should be cancelled if it has not yet started executing.
73pub(crate) trait AbortHandle: Send + Sync {
74    fn abort(self: Box<Self>);
75}
76
77pub(crate) type AbortHandleRef = Box<dyn AbortHandle>;
78
79/// A task for driving I/O requests against a source.
80///
81/// Instead of just spawning a future to process requests, we allow each runtime to decide how
82/// spawn the driver for the request stream. This allows runtimes to shared, parallelize, further
83/// spawn, or otherwise manage the I/O task as they see fit.
84///
85// NOTE(ngates): We could in theory make IoSource support as_any if we wanted each runtime to implement the
86// actual read logic themselves? Not sure yet...
87pub(crate) struct IoTask {
88    pub(crate) source: ReadSourceRef,
89    pub(crate) stream: BoxStream<'static, IoRequest>,
90}
91
92impl IoTask {
93    pub(crate) fn new(source: ReadSourceRef, stream: BoxStream<'static, IoRequest>) -> Self {
94        IoTask { source, stream }
95    }
96}