mirror of https://github.com/fafhrd91/actix-net
Add System::spawn
This commit is contained in:
parent
978e4f25fb
commit
07dec1efa4
|
@ -11,6 +11,7 @@ use std::{
|
||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
|
use crate::task::JoinHandle;
|
||||||
use crate::{arbiter::ArbiterHandle, runtime::default_tokio_runtime, Arbiter, Runtime};
|
use crate::{arbiter::ArbiterHandle, runtime::default_tokio_runtime, Arbiter, Runtime};
|
||||||
|
|
||||||
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
|
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
@ -144,6 +145,27 @@ impl System {
|
||||||
let _ = self.sys_tx.send(SystemCommand::Exit(code));
|
let _ = self.sys_tx.send(SystemCommand::Exit(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send an async task to [System] and spawn running it.
|
||||||
|
/// Returned [JoinHandle](crate::task::JoinHandle) can be used to await for the task's output.
|
||||||
|
///
|
||||||
|
/// # Error
|
||||||
|
/// [actix_rt::spawn](crate::spawn) can not be used inside `System::spawn`.
|
||||||
|
pub fn spawn<T>(task: T) -> JoinHandle<T::Output>
|
||||||
|
where
|
||||||
|
T: Future + Send + 'static,
|
||||||
|
T::Output: Send + 'static,
|
||||||
|
{
|
||||||
|
tokio::spawn(async {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
System::current().arbiter().spawn(async move {
|
||||||
|
let res = tokio::spawn(task).await;
|
||||||
|
let _ = tx.send(res);
|
||||||
|
});
|
||||||
|
// unwrap would be caught by tokio and output as JoinError
|
||||||
|
rx.await.unwrap().unwrap()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn tx(&self) -> &mpsc::UnboundedSender<SystemCommand> {
|
pub(crate) fn tx(&self) -> &mpsc::UnboundedSender<SystemCommand> {
|
||||||
&self.sys_tx
|
&self.sys_tx
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,3 +298,48 @@ fn try_current_no_system() {
|
||||||
fn try_current_with_system() {
|
fn try_current_with_system() {
|
||||||
System::new().block_on(async { assert!(System::try_current().is_some()) });
|
System::new().block_on(async { assert!(System::try_current().is_some()) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn system_spawn() {
|
||||||
|
System::new().block_on(async {
|
||||||
|
// Test detached with dropped handle
|
||||||
|
let num = Arc::new(AtomicBool::new(false));
|
||||||
|
let num_clone = num.clone();
|
||||||
|
System::spawn(async move {
|
||||||
|
actix_rt::time::sleep(Duration::from_millis(500)).await;
|
||||||
|
num_clone.store(true, Ordering::SeqCst);
|
||||||
|
});
|
||||||
|
|
||||||
|
let now = Instant::now();
|
||||||
|
while !num.load(Ordering::SeqCst) {
|
||||||
|
actix_rt::time::sleep(Duration::from_millis(500)).await;
|
||||||
|
if now.elapsed() > Duration::from_secs(10) {
|
||||||
|
panic!("System::spawn deadlocked")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test join handle await
|
||||||
|
let num = Arc::new(AtomicBool::new(false));
|
||||||
|
let num_clone = num.clone();
|
||||||
|
System::spawn(async move {
|
||||||
|
actix_rt::task::yield_now().await;
|
||||||
|
num_clone.store(true, Ordering::SeqCst);
|
||||||
|
actix_rt::task::yield_now().await;
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(num.load(Ordering::SeqCst));
|
||||||
|
|
||||||
|
// test extra actix_rt::spawn
|
||||||
|
let res = System::spawn(async move {
|
||||||
|
actix_rt::task::yield_now().await;
|
||||||
|
actix_rt::spawn(async {
|
||||||
|
actix_rt::task::yield_now().await;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(res.is_err())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue