Skip to content

Commit ca0ed1e

Browse files
committed
chore: Fix CI issues
I also add a more expansive comment detailing the safety conditions of our usage of `async-task`. Signed-off-by: John Nunley <[email protected]>
1 parent 72febd5 commit ca0ed1e

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

src/lib.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,30 @@ impl<'a> Executor<'a> {
239239
};
240240

241241
// Create the task and register it in the set of active tasks.
242-
let (runnable, task) = unsafe {
243-
Builder::new()
244-
.propagate_panic(true)
245-
.spawn_unchecked(|()| future, self.schedule())
246-
};
242+
//
243+
// SAFETY:
244+
//
245+
// If `future` is not `Send`, this must be a `LocalExecutor` as per this
246+
// function's unsafe precondition. Since `LocalExecutor` is `!Sync`,
247+
// `try_tick`, `tick` and `run` can only be called from the origin
248+
// thread of the `LocalExecutor`. Similarly, `spawn` can only be called
249+
// from the origin thread, ensuring that `future` and the executor share
250+
// the same origin thread. The `Runnable` can be scheduled from other
251+
// threads, but because of the above `Runnable` can only be called or
252+
// dropped on the origin thread.
253+
//
254+
// `future` is not `'static`, but we make sure that the `Runnable` does
255+
// not outlive `'a`. When the executor is dropped, the `active` field is
256+
// drained and all of the `Waker`s are woken. Then, the queue inside of
257+
// the `Executor` is drained of all of its runnables. This ensures that
258+
// runnables are dropped and this precondition is satisfied.
259+
//
260+
// `self.schedule()` is `Send`, `Sync` and `'static`, as checked below.
261+
// Therefore we do not need to worry about what is done with the
262+
// `Waker`.
263+
let (runnable, task) = Builder::new()
264+
.propagate_panic(true)
265+
.spawn_unchecked(|()| future, self.schedule());
247266
entry.insert(runnable.waker());
248267

249268
runnable.schedule();
@@ -1068,6 +1087,7 @@ fn _ensure_send_and_sync() {
10681087

10691088
fn is_send<T: Send>(_: T) {}
10701089
fn is_sync<T: Sync>(_: T) {}
1090+
fn is_static<T: 'static>(_: T) {}
10711091

10721092
is_send::<Executor<'_>>(Executor::new());
10731093
is_sync::<Executor<'_>>(Executor::new());
@@ -1077,6 +1097,9 @@ fn _ensure_send_and_sync() {
10771097
is_sync(ex.run(pending::<()>()));
10781098
is_send(ex.tick());
10791099
is_sync(ex.tick());
1100+
is_send(ex.schedule());
1101+
is_sync(ex.schedule());
1102+
is_static(ex.schedule());
10801103

10811104
/// ```compile_fail
10821105
/// use async_executor::LocalExecutor;

tests/spawn_many.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn spawn_many() {
88

99
// Spawn a lot of tasks.
1010
let mut tasks = vec![];
11-
ex.spawn_many((0..50_000).map(|i| future::ready(i)), &mut tasks);
11+
ex.spawn_many((0..50_000).map(future::ready), &mut tasks);
1212

1313
// Run all of the tasks in parallel.
1414
ex.run(async move {
@@ -27,7 +27,7 @@ fn spawn_many_local() {
2727

2828
// Spawn a lot of tasks.
2929
let mut tasks = vec![];
30-
ex.spawn_many((0..50_000).map(|i| future::ready(i)), &mut tasks);
30+
ex.spawn_many((0..50_000).map(future::ready), &mut tasks);
3131

3232
// Run all of the tasks in parallel.
3333
ex.run(async move {

0 commit comments

Comments
 (0)