StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.
| 1 | use std::sync::Arc; |
| 2 | |
| 3 | use futures::{future::LocalBoxFuture, Future, FutureExt}; |
| 4 | use futures_util::future::{AbortHandle, Abortable}; |
| 5 | use wasm_bindgen_futures::spawn_local; |
| 6 | |
| 7 | use crate::{platform, r#async::executor::Error}; |
| 8 | |
| 9 | /// A handle to a task that will run on the main thread. |
| 10 | pub struct ForegroundTask; |
| 11 | |
| 12 | impl ForegroundTask { |
| 13 | /// Detaches the task to let it keep running in the background. |
| 14 | pub fn detach(self) {} |
| 15 | } |
| 16 | |
| 17 | /// A handle to a task that will run in the background. |
| 18 | /// |
| 19 | /// In practice, for wasm, this task will be executed on the singular main |
| 20 | /// thread that all JavaScript code is run on. |
| 21 | pub struct BackgroundTask; |
| 22 | |
| 23 | impl BackgroundTask { |
| 24 | /// Detaches the task to let it keep running in the background. |
| 25 | pub fn detach(self) {} |
| 26 | } |
| 27 | |
| 28 | /// An executor that can be used to run tasks on the main thread. |
| 29 | pub struct Foreground; |
| 30 | |
| 31 | impl Foreground { |
| 32 | pub fn platform(_delegate: Arc<dyn platform::DispatchDelegate>) -> Result<Self, Error> { |
| 33 | Ok(Foreground) |
| 34 | } |
| 35 | |
| 36 | pub fn test() -> Self { |
| 37 | Foreground |
| 38 | } |
| 39 | |
| 40 | /// Schedule an asynchronous task to run on the main thread. |
| 41 | /// |
| 42 | /// If you have a boxed future, use `spawn_boxed` instead. |
| 43 | pub fn spawn(&self, future: impl Future<Output = ()> + 'static) -> ForegroundTask { |
| 44 | self.spawn_boxed(future.boxed_local()) |
| 45 | } |
| 46 | |
| 47 | /// Schedule an asynchronous task to run on the main thread. |
| 48 | /// |
| 49 | /// This takes in a boxed future in order to avoid monomorphizing the |
| 50 | /// underlying task implementation. `spawn_boxed` generates significantly |
| 51 | /// less code than a generic implementation, with no noticeable performance |
| 52 | /// impact. |
| 53 | pub fn spawn_boxed(&self, future: LocalBoxFuture<'static, ()>) -> ForegroundTask { |
| 54 | spawn_local(future); |
| 55 | ForegroundTask |
| 56 | } |
| 57 | |
| 58 | /// Schedules an abortable asynchronous task to run on the main thread. |
| 59 | /// |
| 60 | /// This is the same as `spawn()` except the task may be aborted using the returned |
| 61 | /// [`AbortHandle`]. |
| 62 | pub fn spawn_abortable( |
| 63 | &self, |
| 64 | future: impl Future<Output = ()> + 'static, |
| 65 | ) -> (ForegroundTask, AbortHandle) { |
| 66 | let (handle, registration) = AbortHandle::new_pair(); |
| 67 | let task = self.spawn(Abortable::new(future, registration).map(|_| ())); |
| 68 | (task, handle) |
| 69 | } |
| 70 | |
| 71 | pub async fn run<T: 'static>(&'_ self, future: impl Future<Output = T> + 'static) -> T { |
| 72 | future.await |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | /// An executor that can be used to run background tasks. |
| 77 | /// |
| 78 | /// In practice, for wasm, these tasks will be executed on the singular main |
| 79 | /// thread that all JavaScript code is run on. |
| 80 | pub struct Background; |
| 81 | |
| 82 | impl Default for Background { |
| 83 | fn default() -> Self { |
| 84 | Self::new() |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | impl Background { |
| 89 | pub fn new() -> Self { |
| 90 | Background |
| 91 | } |
| 92 | |
| 93 | /// Schedule an asynchronous task to run on a background thread. |
| 94 | /// |
| 95 | /// If you have a boxed future, use `spawn_boxed` instead. |
| 96 | pub fn spawn(&self, future: impl Future<Output = ()> + 'static) -> BackgroundTask { |
| 97 | self.spawn_boxed(future.boxed_local()) |
| 98 | } |
| 99 | |
| 100 | /// Schedule an asynchronous task to run on a background thread. |
| 101 | /// |
| 102 | /// This takes in a boxed future in order to avoid monomorphizing the |
| 103 | /// underlying task implementation. `spawn_boxed` generates significantly |
| 104 | /// less code than a generic implementation, with no noticeable performance |
| 105 | /// impact. |
| 106 | pub fn spawn_boxed(&self, future: LocalBoxFuture<'static, ()>) -> BackgroundTask { |
| 107 | spawn_local(future); |
| 108 | BackgroundTask |
| 109 | } |
| 110 | |
| 111 | /// Schedules an abortable asynchronous task to run on a background thread. |
| 112 | /// |
| 113 | /// This is the same as `spawn()` except the task may be aborted using the returned |
| 114 | /// [`AbortHandle`]. |
| 115 | pub fn spawn_abortable( |
| 116 | &self, |
| 117 | future: impl Future<Output = ()> + 'static, |
| 118 | ) -> (BackgroundTask, AbortHandle) { |
| 119 | let (handle, registration) = AbortHandle::new_pair(); |
| 120 | let task = self.spawn(Abortable::new(future, registration).map(|_| ())); |
| 121 | (task, handle) |
| 122 | } |
| 123 | } |
| 124 |