@@ -6,7 +6,7 @@ use std::panic::{RefUnwindSafe, UnwindSafe};
6
6
use std:: rc:: Rc ;
7
7
use std:: task:: { Poll , Waker } ;
8
8
9
- use async_task:: { Builder , Runnable } ;
9
+ use async_task:: { Builder , Runnable , Schedule } ;
10
10
use futures_lite:: { future, prelude:: * } ;
11
11
use slab:: Slab ;
12
12
@@ -103,11 +103,12 @@ impl<'a> LocalExecutor<'a> {
103
103
/// });
104
104
/// ```
105
105
pub fn spawn < T : ' a > ( & self , future : impl Future < Output = T > + ' a ) -> Task < T > {
106
+ let state = self . state_as_rc ( ) ;
106
107
// SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
107
108
// `LocalExecutor` is !Send, there is no way to have concurrent access to the
108
109
// values in `State`, including the active field.
109
110
let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
110
- self . spawn_inner ( future, active)
111
+ Self :: spawn_inner ( state , future, active, self . schedule ( ) )
111
112
}
112
113
113
114
/// Spawns many tasks onto the executor.
@@ -155,30 +156,34 @@ impl<'a> LocalExecutor<'a> {
155
156
futures : impl IntoIterator < Item = F > ,
156
157
handles : & mut impl Extend < Task < F :: Output > > ,
157
158
) {
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 ( ) ;
162
161
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
+ } ;
167
172
168
173
// Push the tasks to the user's collection.
169
174
handles. extend ( tasks) ;
170
175
}
171
176
172
177
/// Spawn a future while holding the inner lock.
173
178
fn spawn_inner < T : ' a > (
174
- & self ,
179
+ state : Rc < State > ,
175
180
future : impl Future < Output = T > + ' a ,
176
181
active : & mut Slab < Waker > ,
182
+ schedule : impl Schedule + ' static ,
177
183
) -> Task < T > {
178
184
// Remove the task from the set of active tasks when the future finishes.
179
185
let entry = active. vacant_entry ( ) ;
180
186
let index = entry. key ( ) ;
181
- let state = self . state_as_rc ( ) ;
182
187
let future = AsyncCallOnDrop :: new ( future, move || {
183
188
// SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
184
189
// `LocalExecutor` is !Send, there is no way to have concurrent access to the
@@ -204,16 +209,16 @@ impl<'a> LocalExecutor<'a> {
204
209
// the `Executor` is drained of all of its runnables. This ensures that
205
210
// runnables are dropped and this precondition is satisfied.
206
211
//
207
- // `self. schedule() ` is not `Send` nor `Sync`. As LocalExecutor is not
212
+ // `schedule` is not `Send` nor `Sync`. As LocalExecutor is not
208
213
// `Send`, the `Waker` is guaranteed// to only be used on the same thread
209
214
// it was spawned on.
210
215
//
211
- // `self. schedule() ` is `'static`, and thus will outlive all borrowed
216
+ // `schedule` is `'static`, and thus will outlive all borrowed
212
217
// variables in the future.
213
218
let ( runnable, task) = unsafe {
214
219
Builder :: new ( )
215
220
. propagate_panic ( true )
216
- . spawn_unchecked ( |( ) | future, self . schedule ( ) )
221
+ . spawn_unchecked ( |( ) | future, schedule)
217
222
} ;
218
223
entry. insert ( runnable. waker ( ) ) ;
219
224
0 commit comments