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
1414#[ cfg( all( test, not( feature = "std" ) ) ) ]
15- use core:: cell:: RefCell ;
15+ use core:: cell:: { Rc , RefCell } ;
16+ #[ cfg( test) ]
17+ use core:: convert:: Infallible ;
1618use core:: future:: Future ;
1719#[ cfg( test) ]
1820use core:: pin:: Pin ;
21+ #[ cfg( test) ]
22+ use core:: task:: { Context , Poll } ;
1923
20- /// A generic trait which is able to spawn futures in the background.
24+ /// A generic trait which is able to spawn futures to be polled in the background.
25+ ///
26+ /// When the spawned future completes, the returned [`Self::SpawnedFutureResult`] should resolve
27+ /// with the output of the spawned future.
28+ ///
29+ /// Spawned futures must be polled independently in the background even if the returned
30+ /// [`Self::SpawnedFutureResult`] is dropped without being polled. This matches the semantics of
31+ /// `tokio::spawn`.
2132pub trait FutureSpawner : MaybeSend + MaybeSync + ' static {
33+ /// The error type of [`Self::SpawnedFutureResult`]. This can be used to indicate that the
34+ /// spawned future was cancelled or panicked.
35+ type E ;
36+ /// The result of [`Self::spawn`], a future which completes when the spawned future completes.
37+ type SpawnedFutureResult < O > : Future < Output = Result < O , Self :: E > > + Unpin ;
2238 /// Spawns the given future as a background task.
2339 ///
2440 /// This method MUST NOT block on the given future immediately.
25- fn spawn < T : Future < Output = ( ) > + MaybeSend + ' static > ( & self , future : T ) ;
41+ fn spawn < O : MaybeSend + ' static , T : Future < Output = O > + MaybeSend + ' static > (
42+ & self , future : T ,
43+ ) -> Self :: SpawnedFutureResult < O > ;
2644}
2745
2846#[ cfg( test) ]
@@ -37,6 +55,69 @@ pub(crate) struct FutureQueue(Mutex<Vec<Pin<Box<dyn MaybeSendableFuture>>>>);
3755#[ cfg( all( test, not( feature = "std" ) ) ) ]
3856pub ( crate ) struct FutureQueue ( RefCell < Vec < Pin < Box < dyn MaybeSendableFuture > > > > ) ;
3957
58+ #[ cfg( all( test, feature = "std" ) ) ]
59+ pub struct FutureQueueCompletion < O > ( Arc < Mutex < Option < O > > > ) ;
60+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
61+ pub struct FutureQueueCompletion < O > ( Rc < RefCell < Option < O > > > ) ;
62+
63+ #[ cfg( all( test, feature = "std" ) ) ]
64+ impl < O > FutureQueueCompletion < O > {
65+ fn new ( ) -> Self {
66+ Self ( Arc :: new ( Mutex :: new ( None ) ) )
67+ }
68+
69+ fn complete ( & self , o : O ) {
70+ * self . 0 . lock ( ) . unwrap ( ) = Some ( o) ;
71+ }
72+ }
73+
74+ #[ cfg( all( test, feature = "std" ) ) ]
75+ impl < O > Clone for FutureQueueCompletion < O > {
76+ fn clone ( & self ) -> Self {
77+ Self ( self . 0 . clone ( ) )
78+ }
79+ }
80+
81+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
82+ impl < O > FutureQueueCompletion < O > {
83+ fn new ( ) -> Self {
84+ Self ( Rc :: new ( Mutex :: new ( None ) ) )
85+ }
86+
87+ fn complete ( & self , o : O ) {
88+ * self . 0 . lock ( ) . unwrap ( ) = Some ( o) ;
89+ }
90+ }
91+
92+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
93+ impl < O > Clone for FutureQueueCompletion < O > {
94+ fn clone ( & self ) -> Self {
95+ Self ( self . 0 . clone ( ) )
96+ }
97+ }
98+
99+ #[ cfg( all( test, feature = "std" ) ) ]
100+ impl < O > Future for FutureQueueCompletion < O > {
101+ type Output = Result < O , Infallible > ;
102+ fn poll ( self : Pin < & mut Self > , _: & mut Context < ' _ > ) -> Poll < Result < O , Infallible > > {
103+ match Pin :: into_inner ( self ) . 0 . lock ( ) . unwrap ( ) . take ( ) {
104+ None => Poll :: Pending ,
105+ Some ( o) => Poll :: Ready ( Ok ( o) ) ,
106+ }
107+ }
108+ }
109+
110+ #[ cfg( all( test, not( feature = "std" ) ) ) ]
111+ impl < O > Future for FutureQueueCompletion < O > {
112+ type Output = Result < O , Infallible > ;
113+ fn poll ( self : Pin < & mut Self > , _: & mut Context < ' _ > ) -> Poll < Result < O , Infallible > > {
114+ match Pin :: into_inner ( self ) . 0 . get_mut ( ) . take ( ) {
115+ None => Poll :: Pending ,
116+ Some ( o) => Poll :: Ready ( Ok ( o) ) ,
117+ }
118+ }
119+ }
120+
40121#[ cfg( test) ]
41122impl FutureQueue {
42123 pub ( crate ) fn new ( ) -> Self {
@@ -84,7 +165,16 @@ impl FutureQueue {
84165
85166#[ cfg( test) ]
86167impl FutureSpawner for FutureQueue {
87- fn spawn < T : Future < Output = ( ) > + MaybeSend + ' static > ( & self , future : T ) {
168+ type E = Infallible ;
169+ type SpawnedFutureResult < O > = FutureQueueCompletion < O > ;
170+ fn spawn < O : MaybeSend + ' static , F : Future < Output = O > + MaybeSend + ' static > (
171+ & self , f : F ,
172+ ) -> FutureQueueCompletion < O > {
173+ let completion = FutureQueueCompletion :: new ( ) ;
174+ let compl_ref = completion. clone ( ) ;
175+ let future = async move {
176+ compl_ref. complete ( f. await ) ;
177+ } ;
88178 #[ cfg( feature = "std" ) ]
89179 {
90180 self . 0 . lock ( ) . unwrap ( ) . push ( Box :: pin ( future) ) ;
@@ -93,14 +183,24 @@ impl FutureSpawner for FutureQueue {
93183 {
94184 self . 0 . borrow_mut ( ) . push ( Box :: pin ( future) ) ;
95185 }
186+ completion
96187 }
97188}
98189
99190#[ cfg( test) ]
100191impl < D : core:: ops:: Deref < Target = FutureQueue > + MaybeSend + MaybeSync + ' static > FutureSpawner
101192 for D
102193{
103- fn spawn < T : Future < Output = ( ) > + MaybeSend + ' static > ( & self , future : T ) {
194+ type E = Infallible ;
195+ type SpawnedFutureResult < O > = FutureQueueCompletion < O > ;
196+ fn spawn < O : MaybeSend + ' static , F : Future < Output = O > + MaybeSend + ' static > (
197+ & self , f : F ,
198+ ) -> FutureQueueCompletion < O > {
199+ let completion = FutureQueueCompletion :: new ( ) ;
200+ let compl_ref = completion. clone ( ) ;
201+ let future = async move {
202+ compl_ref. complete ( f. await ) ;
203+ } ;
104204 #[ cfg( feature = "std" ) ]
105205 {
106206 self . 0 . lock ( ) . unwrap ( ) . push ( Box :: pin ( future) ) ;
@@ -109,5 +209,6 @@ impl<D: core::ops::Deref<Target = FutureQueue> + MaybeSend + MaybeSync + 'static
109209 {
110210 self . 0 . borrow_mut ( ) . push ( Box :: pin ( future) ) ;
111211 }
212+ completion
112213 }
113214}
0 commit comments