@@ -6,7 +6,7 @@ use std::panic::{RefUnwindSafe, UnwindSafe};
66use std:: rc:: Rc ;
77use std:: task:: { Poll , Waker } ;
88
9- use async_task:: { Builder , Runnable } ;
9+ use async_task:: { Builder , Runnable , Schedule } ;
1010use futures_lite:: { future, prelude:: * } ;
1111use slab:: Slab ;
1212
@@ -103,11 +103,12 @@ impl<'a> LocalExecutor<'a> {
103103 /// });
104104 /// ```
105105 pub fn spawn < T : ' a > ( & self , future : impl Future < Output = T > + ' a ) -> Task < T > {
106+ let state = self . state_as_rc ( ) ;
106107 // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
107108 // `LocalExecutor` is !Send, there is no way to have concurrent access to the
108109 // values in `State`, including the active field.
109110 let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
110- self . spawn_inner ( future, active)
111+ Self :: spawn_inner ( state , future, active, self . schedule ( ) )
111112 }
112113
113114 /// Spawns many tasks onto the executor.
@@ -155,30 +156,34 @@ impl<'a> LocalExecutor<'a> {
155156 futures : impl IntoIterator < Item = F > ,
156157 handles : & mut impl Extend < Task < F :: Output > > ,
157158 ) {
158- // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
159- // `LocalExecutor` is !Send, there is no way to have concurrent access to the
160- // values in `State`, including the active field.
161- let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
159+ let tasks = {
160+ let state = self . state_as_rc ( ) ;
162161
163- // Convert the futures into tasks.
164- let tasks = futures
165- . into_iter ( )
166- . map ( move |future| self . spawn_inner ( future, active) ) ;
162+ // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
163+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
164+ // values in `State`, including the active field.
165+ let active = unsafe { & mut * state. active . get ( ) } ;
166+
167+ // Convert the futures into tasks.
168+ futures. into_iter ( ) . map ( move |future| {
169+ Self :: spawn_inner ( state. clone ( ) , future, active, self . schedule ( ) )
170+ } )
171+ } ;
167172
168173 // Push the tasks to the user's collection.
169174 handles. extend ( tasks) ;
170175 }
171176
172177 /// Spawn a future while holding the inner lock.
173178 fn spawn_inner < T : ' a > (
174- & self ,
179+ state : Rc < State > ,
175180 future : impl Future < Output = T > + ' a ,
176181 active : & mut Slab < Waker > ,
182+ schedule : impl Schedule + ' static ,
177183 ) -> Task < T > {
178184 // Remove the task from the set of active tasks when the future finishes.
179185 let entry = active. vacant_entry ( ) ;
180186 let index = entry. key ( ) ;
181- let state = self . state_as_rc ( ) ;
182187 let future = AsyncCallOnDrop :: new ( future, move || {
183188 // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
184189 // `LocalExecutor` is !Send, there is no way to have concurrent access to the
@@ -204,16 +209,16 @@ impl<'a> LocalExecutor<'a> {
204209 // the `Executor` is drained of all of its runnables. This ensures that
205210 // runnables are dropped and this precondition is satisfied.
206211 //
207- // `self. schedule() ` is not `Send` nor `Sync`. As LocalExecutor is not
212+ // `schedule` is not `Send` nor `Sync`. As LocalExecutor is not
208213 // `Send`, the `Waker` is guaranteed// to only be used on the same thread
209214 // it was spawned on.
210215 //
211- // `self. schedule() ` is `'static`, and thus will outlive all borrowed
216+ // `schedule` is `'static`, and thus will outlive all borrowed
212217 // variables in the future.
213218 let ( runnable, task) = unsafe {
214219 Builder :: new ( )
215220 . propagate_panic ( true )
216- . spawn_unchecked ( |( ) | future, self . schedule ( ) )
221+ . spawn_unchecked ( |( ) | future, schedule)
217222 } ;
218223 entry. insert ( runnable. waker ( ) ) ;
219224
0 commit comments