Skip to content

Commit 2b1edb9

Browse files
spawn should allow futures with non-unit outputs (#369)
Co-authored-by: Rob Ede <robjtede@icloud.com>
1 parent 4644fa4 commit 2b1edb9

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

actix-rt/CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Changes
22

33
## Unreleased - 2021-xx-xx
4+
* The `spawn` method can now resolve with non-unit outputs. [#369]
5+
6+
[#369]: https://github.com/actix/actix-net/pull/369
47

58

69
## 2.2.0 - 2021-03-29

actix-rt/src/lib.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ use tokio::task::JoinHandle;
4646
// Cannot define a main macro when compiled into test harness.
4747
// Workaround for https://github.com/rust-lang/rust/issues/62127.
4848
#[cfg(all(feature = "macros", not(test)))]
49-
pub use actix_macros::{main, test};
49+
pub use actix_macros::main;
50+
51+
#[cfg(feature = "macros")]
52+
pub use actix_macros::test;
5053

5154
mod arbiter;
5255
mod runtime;
@@ -155,14 +158,41 @@ pub mod task {
155158
pub use tokio::task::{spawn_blocking, yield_now, JoinError, JoinHandle};
156159
}
157160

158-
/// Spawns a future on the current thread.
161+
/// Spawns a future on the current thread as a new task.
162+
///
163+
/// If not immediately awaited, the task can be cancelled using [`JoinHandle::abort`].
164+
///
165+
/// The provided future is spawned as a new task; therefore, panics are caught.
159166
///
160167
/// # Panics
161168
/// Panics if Actix system is not running.
169+
///
170+
/// # Examples
171+
/// ```
172+
/// # use std::time::Duration;
173+
/// # actix_rt::Runtime::new().unwrap().block_on(async {
174+
/// // task resolves successfully
175+
/// assert_eq!(actix_rt::spawn(async { 1 }).await.unwrap(), 1);
176+
///
177+
/// // task panics
178+
/// assert!(actix_rt::spawn(async {
179+
/// panic!("panic is caught at task boundary");
180+
/// })
181+
/// .await
182+
/// .unwrap_err()
183+
/// .is_panic());
184+
///
185+
/// // task is cancelled before completion
186+
/// let handle = actix_rt::spawn(actix_rt::time::sleep(Duration::from_secs(100)));
187+
/// handle.abort();
188+
/// assert!(handle.await.unwrap_err().is_cancelled());
189+
/// # });
190+
/// ```
162191
#[inline]
163-
pub fn spawn<Fut>(f: Fut) -> JoinHandle<()>
192+
pub fn spawn<Fut>(f: Fut) -> JoinHandle<Fut::Output>
164193
where
165-
Fut: Future<Output = ()> + 'static,
194+
Fut: Future + 'static,
195+
Fut::Output: 'static,
166196
{
167197
tokio::task::spawn_local(f)
168198
}

actix-rt/tests/tests.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
future::Future,
23
sync::{
34
atomic::{AtomicBool, Ordering},
45
mpsc::channel,
@@ -8,7 +9,7 @@ use std::{
89
time::{Duration, Instant},
910
};
1011

11-
use actix_rt::{Arbiter, System};
12+
use actix_rt::{task::JoinError, Arbiter, System};
1213
use tokio::sync::oneshot;
1314

1415
#[test]
@@ -298,3 +299,27 @@ fn try_current_no_system() {
298299
fn try_current_with_system() {
299300
System::new().block_on(async { assert!(System::try_current().is_some()) });
300301
}
302+
303+
#[allow(clippy::unit_cmp)]
304+
#[test]
305+
fn spawn_local() {
306+
System::new().block_on(async {
307+
// demonstrate that spawn -> R is strictly more capable than spawn -> ()
308+
309+
assert_eq!(actix_rt::spawn(async {}).await.unwrap(), ());
310+
assert_eq!(actix_rt::spawn(async { 1 }).await.unwrap(), 1);
311+
assert!(actix_rt::spawn(async { panic!("") }).await.is_err());
312+
313+
actix_rt::spawn(async { tokio::time::sleep(Duration::from_millis(50)).await })
314+
.await
315+
.unwrap();
316+
317+
fn g<F: Future<Output = Result<(), JoinError>>>(_f: F) {}
318+
g(actix_rt::spawn(async {}));
319+
// g(actix_rt::spawn(async { 1 })); // compile err
320+
321+
fn h<F: Future<Output = Result<R, JoinError>>, R>(_f: F) {}
322+
h(actix_rt::spawn(async {}));
323+
h(actix_rt::spawn(async { 1 }));
324+
})
325+
}

0 commit comments

Comments
 (0)