mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-01 03:02:28 +03:00
feat(core): async_runtime
handle
API, spawn
returns JoinHandle
(#2399)
This commit is contained in:
parent
bdda79cfbc
commit
9aeb04faf4
5
.changes/async-runtime-handle-api.md
Normal file
5
.changes/async-runtime-handle-api.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch
|
||||
---
|
||||
|
||||
Add `handle` API to `tauri::async_runtime`.
|
5
.changes/async-runtime-spawn-returns-join-handle.md
Normal file
5
.changes/async-runtime-spawn-returns-join-handle.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch
|
||||
---
|
||||
|
||||
**Breaking change:** The `tauri::async_runtime::spawn` function now returns `tauri::async_runtime::JoinHandle<T>`.
|
@ -69,7 +69,8 @@ os_pipe = { version = "0.9", optional = true }
|
||||
rfd = "0.4.2"
|
||||
raw-window-handle = { version = "0.3.3", optional = true }
|
||||
minisign-verify = { version = "0.1", optional = true }
|
||||
os_info = { version = "3.0.6", optional = true}
|
||||
os_info = { version = "3.0.6", optional = true }
|
||||
futures-lite = "1.12"
|
||||
|
||||
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||
gtk = { version = "0.14", features = [ "v3_20" ] }
|
||||
@ -86,6 +87,7 @@ serde = { version = "1.0", features = [ "derive" ] }
|
||||
quickcheck = "1.0.3"
|
||||
quickcheck_macros = "1.0.0"
|
||||
tokio-test = "0.4.2"
|
||||
tokio = { version = "1.9", features = [ "full" ] }
|
||||
mockito = "0.30"
|
||||
|
||||
[features]
|
||||
|
@ -7,17 +7,73 @@
|
||||
//! Fox more complex use cases, consider creating your own runtime.
|
||||
//! For command handlers, it's recommended to use a plain `async fn` command.
|
||||
|
||||
use futures_lite::future::FutureExt;
|
||||
use once_cell::sync::OnceCell;
|
||||
use tokio::runtime::Runtime;
|
||||
pub use tokio::sync::{
|
||||
mpsc::{channel, Receiver, Sender},
|
||||
Mutex, RwLock,
|
||||
pub use tokio::{
|
||||
runtime::Handle,
|
||||
sync::{
|
||||
mpsc::{channel, Receiver, Sender},
|
||||
Mutex, RwLock,
|
||||
},
|
||||
task::JoinHandle as TokioJoinHandle,
|
||||
};
|
||||
|
||||
use std::future::Future;
|
||||
use std::{
|
||||
fmt,
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
static RUNTIME: OnceCell<Runtime> = OnceCell::new();
|
||||
|
||||
/// An owned permission to join on a task (await its termination).
|
||||
#[derive(Debug)]
|
||||
pub struct JoinHandle<T>(TokioJoinHandle<T>);
|
||||
|
||||
impl<T> Future for JoinHandle<T> {
|
||||
type Output = crate::Result<T>;
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self
|
||||
.0
|
||||
.poll(cx)
|
||||
.map_err(|e| crate::Error::JoinError(Box::new(e)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Runtime handle definition.
|
||||
pub trait RuntimeHandle: fmt::Debug + Clone + Sync + Sync {
|
||||
/// Spawn a future onto the runtime.
|
||||
fn spawn<F: Future>(&self, task: F) -> JoinHandle<F::Output>
|
||||
where
|
||||
F: Future + Send + 'static,
|
||||
F::Output: Send + 'static;
|
||||
|
||||
/// Run a future to completion on runtime.
|
||||
fn block_on<F: Future>(&self, task: F) -> F::Output;
|
||||
}
|
||||
|
||||
impl RuntimeHandle for Handle {
|
||||
fn spawn<F: Future>(&self, task: F) -> JoinHandle<F::Output>
|
||||
where
|
||||
F: Future + Send + 'static,
|
||||
F::Output: Send + 'static,
|
||||
{
|
||||
JoinHandle(self.spawn(task))
|
||||
}
|
||||
|
||||
fn block_on<F: Future>(&self, task: F) -> F::Output {
|
||||
self.block_on(task)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a handle to the async runtime.
|
||||
pub fn handle() -> impl RuntimeHandle {
|
||||
let runtime = RUNTIME.get_or_init(|| Runtime::new().unwrap());
|
||||
runtime.handle().clone()
|
||||
}
|
||||
|
||||
/// Run a future to completion on runtime.
|
||||
pub fn block_on<F: Future>(task: F) -> F::Output {
|
||||
let runtime = RUNTIME.get_or_init(|| Runtime::new().unwrap());
|
||||
@ -25,11 +81,28 @@ pub fn block_on<F: Future>(task: F) -> F::Output {
|
||||
}
|
||||
|
||||
/// Spawn a future onto the runtime.
|
||||
pub fn spawn<F>(task: F)
|
||||
pub fn spawn<F>(task: F) -> JoinHandle<F::Output>
|
||||
where
|
||||
F: Future + Send + 'static,
|
||||
F::Output: Send + 'static,
|
||||
{
|
||||
let runtime = RUNTIME.get_or_init(|| Runtime::new().unwrap());
|
||||
runtime.spawn(task);
|
||||
JoinHandle(runtime.spawn(task))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[tokio::test]
|
||||
async fn handle_spawn() {
|
||||
let handle = handle();
|
||||
let join = handle.spawn(async { 5 });
|
||||
assert_eq!(join.await.unwrap(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handle_block_on() {
|
||||
let handle = handle();
|
||||
assert_eq!(handle.block_on(async { 0 }), 0);
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,9 @@ pub enum Error {
|
||||
/// user-provided URLs and paths.
|
||||
#[error("invalid url: {0}")]
|
||||
InvalidUrl(url::ParseError),
|
||||
/// Task join error.
|
||||
#[error(transparent)]
|
||||
JoinError(Box<dyn std::error::Error + Send>),
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for Error {
|
||||
|
@ -490,7 +490,7 @@ pub(crate) fn listener<R: Runtime>(
|
||||
// emit {"status": "DONE"}
|
||||
send_status_update(window.clone(), EVENT_STATUS_SUCCESS, None);
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
} else {
|
||||
send_status_update(window.clone(), EVENT_STATUS_UPTODATE, None);
|
||||
@ -500,7 +500,7 @@ pub(crate) fn listener<R: Runtime>(
|
||||
send_status_update(window.clone(), EVENT_STATUS_ERROR, Some(e.to_string()));
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user