@@ -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,13 @@ 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
+ let schedule = Self :: schedule ( state. clone ( ) ) ;
112
+ Self :: spawn_inner ( state, future, active, schedule)
111
113
}
112
114
113
115
/// Spawns many tasks onto the executor.
@@ -155,30 +157,35 @@ impl<'a> LocalExecutor<'a> {
155
157
futures : impl IntoIterator < Item = F > ,
156
158
handles : & mut impl Extend < Task < F :: Output > > ,
157
159
) {
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 ( ) } ;
160
+ let tasks = {
161
+ let state = self . state_as_rc ( ) ;
162
162
163
- // Convert the futures into tasks.
164
- let tasks = futures
165
- . into_iter ( )
166
- . map ( move |future| self . spawn_inner ( future, active) ) ;
163
+ // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
164
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
165
+ // values in `State`, including the active field.
166
+ let active = unsafe { & mut * state. active . get ( ) } ;
167
+
168
+ // Convert the futures into tasks.
169
+ futures. into_iter ( ) . map ( move |future| {
170
+ let schedule = Self :: schedule ( state. clone ( ) ) ;
171
+ Self :: spawn_inner ( state. clone ( ) , future, active, schedule)
172
+ } )
173
+ } ;
167
174
168
175
// Push the tasks to the user's collection.
169
176
handles. extend ( tasks) ;
170
177
}
171
178
172
179
/// Spawn a future while holding the inner lock.
173
180
fn spawn_inner < T : ' a > (
174
- & self ,
181
+ state : Rc < State > ,
175
182
future : impl Future < Output = T > + ' a ,
176
183
active : & mut Slab < Waker > ,
184
+ schedule : impl Schedule + ' static ,
177
185
) -> Task < T > {
178
186
// Remove the task from the set of active tasks when the future finishes.
179
187
let entry = active. vacant_entry ( ) ;
180
188
let index = entry. key ( ) ;
181
- let state = self . state_as_rc ( ) ;
182
189
let future = AsyncCallOnDrop :: new ( future, move || {
183
190
// SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
184
191
// `LocalExecutor` is !Send, there is no way to have concurrent access to the
@@ -204,16 +211,16 @@ impl<'a> LocalExecutor<'a> {
204
211
// the `Executor` is drained of all of its runnables. This ensures that
205
212
// runnables are dropped and this precondition is satisfied.
206
213
//
207
- // `self. schedule() ` is not `Send` nor `Sync`. As LocalExecutor is not
214
+ // `schedule` is not `Send` nor `Sync`. As LocalExecutor is not
208
215
// `Send`, the `Waker` is guaranteed// to only be used on the same thread
209
216
// it was spawned on.
210
217
//
211
- // `self. schedule() ` is `'static`, and thus will outlive all borrowed
218
+ // `schedule` is `'static`, and thus will outlive all borrowed
212
219
// variables in the future.
213
220
let ( runnable, task) = unsafe {
214
221
Builder :: new ( )
215
222
. propagate_panic ( true )
216
- . spawn_unchecked ( |( ) | future, self . schedule ( ) )
223
+ . spawn_unchecked ( |( ) | future, schedule)
217
224
} ;
218
225
entry. insert ( runnable. waker ( ) ) ;
219
226
@@ -285,9 +292,7 @@ impl<'a> LocalExecutor<'a> {
285
292
}
286
293
287
294
/// Returns a function that schedules a runnable task when it gets woken up.
288
- fn schedule ( & self ) -> impl Fn ( Runnable ) + ' static {
289
- let state = self . state_as_rc ( ) ;
290
-
295
+ fn schedule ( state : Rc < State > ) -> impl Fn ( Runnable ) + ' static {
291
296
move |runnable| {
292
297
{
293
298
// SAFETY: All UnsafeCell accesses to queue are tightly scoped, and because
0 commit comments