88//! environment.
99
1010#[ cfg( all( test, feature = "std" ) ) ]
11- use crate :: sync:: Mutex ;
11+ use crate :: sync:: { Arc , Mutex } ;
1212use crate :: util:: async_poll:: { MaybeSend , MaybeSync } ;
1313
14+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
15+ use alloc:: rc:: Rc ;
16+
1417#[ cfg( all( test, not( feature = "std" ) ) ) ]
1518use core:: cell:: RefCell ;
19+ #[ cfg( test) ]
20+ use core:: convert:: Infallible ;
1621use core:: future:: Future ;
1722#[ cfg( test) ]
1823use core:: pin:: Pin ;
24+ #[ cfg( test) ]
25+ use core:: task:: { Context , Poll } ;
1926
20- /// A generic trait which is able to spawn futures in the background.
27+ /// A generic trait which is able to spawn futures to be polled in the background.
28+ ///
29+ /// When the spawned future completes, the returned [`Self::SpawnedFutureResult`] should resolve
30+ /// with the output of the spawned future.
31+ ///
32+ /// Spawned futures must be polled independently in the background even if the returned
33+ /// [`Self::SpawnedFutureResult`] is dropped without being polled. This matches the semantics of
34+ /// `tokio::spawn`.
2135///
2236/// This is not exported to bindings users as async is only supported in Rust.
2337pub trait FutureSpawner : MaybeSend + MaybeSync + ' static {
38+ /// The error type of [`Self::SpawnedFutureResult`]. This can be used to indicate that the
39+ /// spawned future was cancelled or panicked.
40+ type E ;
41+ /// The result of [`Self::spawn`], a future which completes when the spawned future completes.
42+ type SpawnedFutureResult < O > : Future < Output = Result < O , Self :: E > > + Unpin ;
2443 /// Spawns the given future as a background task.
2544 ///
2645 /// This method MUST NOT block on the given future immediately.
27- fn spawn < T : Future < Output = ( ) > + MaybeSend + ' static > ( & self , future : T ) ;
46+ fn spawn < O : MaybeSend + ' static , T : Future < Output = O > + MaybeSend + ' static > (
47+ & self , future : T ,
48+ ) -> Self :: SpawnedFutureResult < O > ;
2849}
2950
3051#[ cfg( test) ]
@@ -39,6 +60,69 @@ pub(crate) struct FutureQueue(Mutex<Vec<Pin<Box<dyn MaybeSendableFuture>>>>);
3960#[ cfg( all( test, not( feature = "std" ) ) ) ]
4061pub ( crate ) struct FutureQueue ( RefCell < Vec < Pin < Box < dyn MaybeSendableFuture > > > > ) ;
4162
63+ #[ cfg( all( test, feature = "std" ) ) ]
64+ pub struct FutureQueueCompletion < O > ( Arc < Mutex < Option < O > > > ) ;
65+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
66+ pub struct FutureQueueCompletion < O > ( Rc < RefCell < Option < O > > > ) ;
67+
68+ #[ cfg( all( test, feature = "std" ) ) ]
69+ impl < O > FutureQueueCompletion < O > {
70+ fn new ( ) -> Self {
71+ Self ( Arc :: new ( Mutex :: new ( None ) ) )
72+ }
73+
74+ fn complete ( & self , o : O ) {
75+ * self . 0 . lock ( ) . unwrap ( ) = Some ( o) ;
76+ }
77+ }
78+
79+ #[ cfg( all( test, feature = "std" ) ) ]
80+ impl < O > Clone for FutureQueueCompletion < O > {
81+ fn clone ( & self ) -> Self {
82+ Self ( self . 0 . clone ( ) )
83+ }
84+ }
85+
86+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
87+ impl < O > FutureQueueCompletion < O > {
88+ fn new ( ) -> Self {
89+ Self ( Rc :: new ( RefCell :: new ( None ) ) )
90+ }
91+
92+ fn complete ( & self , o : O ) {
93+ * self . 0 . borrow_mut ( ) = Some ( o) ;
94+ }
95+ }
96+
97+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
98+ impl < O > Clone for FutureQueueCompletion < O > {
99+ fn clone ( & self ) -> Self {
100+ Self ( self . 0 . clone ( ) )
101+ }
102+ }
103+
104+ #[ cfg( all( test, feature = "std" ) ) ]
105+ impl < O > Future for FutureQueueCompletion < O > {
106+ type Output = Result < O , Infallible > ;
107+ fn poll ( self : Pin < & mut Self > , _: & mut Context < ' _ > ) -> Poll < Result < O , Infallible > > {
108+ match Pin :: into_inner ( self ) . 0 . lock ( ) . unwrap ( ) . take ( ) {
109+ None => Poll :: Pending ,
110+ Some ( o) => Poll :: Ready ( Ok ( o) ) ,
111+ }
112+ }
113+ }
114+
115+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
116+ impl < O > Future for FutureQueueCompletion < O > {
117+ type Output = Result < O , Infallible > ;
118+ fn poll ( self : Pin < & mut Self > , _: & mut Context < ' _ > ) -> Poll < Result < O , Infallible > > {
119+ match Pin :: into_inner ( self ) . 0 . borrow_mut ( ) . take ( ) {
120+ None => Poll :: Pending ,
121+ Some ( o) => Poll :: Ready ( Ok ( o) ) ,
122+ }
123+ }
124+ }
125+
42126#[ cfg( test) ]
43127impl FutureQueue {
44128 pub ( crate ) fn new ( ) -> Self {
@@ -74,7 +158,6 @@ impl FutureQueue {
74158 futures = self . 0 . borrow_mut ( ) ;
75159 }
76160 futures. retain_mut ( |fut| {
77- use core:: task:: { Context , Poll } ;
78161 let waker = crate :: util:: async_poll:: dummy_waker ( ) ;
79162 match fut. as_mut ( ) . poll ( & mut Context :: from_waker ( & waker) ) {
80163 Poll :: Ready ( ( ) ) => false ,
@@ -86,7 +169,16 @@ impl FutureQueue {
86169
87170#[ cfg( test) ]
88171impl FutureSpawner for FutureQueue {
89- fn spawn < T : Future < Output = ( ) > + MaybeSend + ' static > ( & self , future : T ) {
172+ type E = Infallible ;
173+ type SpawnedFutureResult < O > = FutureQueueCompletion < O > ;
174+ fn spawn < O : MaybeSend + ' static , F : Future < Output = O > + MaybeSend + ' static > (
175+ & self , f : F ,
176+ ) -> FutureQueueCompletion < O > {
177+ let completion = FutureQueueCompletion :: new ( ) ;
178+ let compl_ref = completion. clone ( ) ;
179+ let future = async move {
180+ compl_ref. complete ( f. await ) ;
181+ } ;
90182 #[ cfg( feature = "std" ) ]
91183 {
92184 self . 0 . lock ( ) . unwrap ( ) . push ( Box :: pin ( future) ) ;
@@ -95,14 +187,24 @@ impl FutureSpawner for FutureQueue {
95187 {
96188 self . 0 . borrow_mut ( ) . push ( Box :: pin ( future) ) ;
97189 }
190+ completion
98191 }
99192}
100193
101194#[ cfg( test) ]
102195impl < D : core:: ops:: Deref < Target = FutureQueue > + MaybeSend + MaybeSync + ' static > FutureSpawner
103196 for D
104197{
105- fn spawn < T : Future < Output = ( ) > + MaybeSend + ' static > ( & self , future : T ) {
198+ type E = Infallible ;
199+ type SpawnedFutureResult < O > = FutureQueueCompletion < O > ;
200+ fn spawn < O : MaybeSend + ' static , F : Future < Output = O > + MaybeSend + ' static > (
201+ & self , f : F ,
202+ ) -> FutureQueueCompletion < O > {
203+ let completion = FutureQueueCompletion :: new ( ) ;
204+ let compl_ref = completion. clone ( ) ;
205+ let future = async move {
206+ compl_ref. complete ( f. await ) ;
207+ } ;
106208 #[ cfg( feature = "std" ) ]
107209 {
108210 self . 0 . lock ( ) . unwrap ( ) . push ( Box :: pin ( future) ) ;
@@ -111,5 +213,6 @@ impl<D: core::ops::Deref<Target = FutureQueue> + MaybeSend + MaybeSync + 'static
111213 {
112214 self . 0 . borrow_mut ( ) . push ( Box :: pin ( future) ) ;
113215 }
216+ completion
114217 }
115218}
0 commit comments