Skip to content

Commit

Permalink
bugfix: Ensure that ex.run() produces a Send future
Browse files Browse the repository at this point in the history
This commit makes sure that the run() and tick() functions produce
futures that are Send and Sync, to prevent a regression introduced in
PR #37. Tests are also added to prevent this regression in the future.

Signed-off-by: John Nunley <dev@notgull.net>
  • Loading branch information
notgull committed Aug 21, 2023
1 parent e195733 commit a5ff8df
Showing 1 changed file with 37 additions and 3 deletions.
40 changes: 37 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl<'a> Executor<'a> {
// Try to push into the local queue.
LocalQueue::with(|local_queue| {
// Make sure that we don't accidentally push to an executor that isn't ours.
if !std::ptr::eq(local_queue.state, &*state) {
if local_queue.state != &*state as *const State as usize {
return;
}

Expand Down Expand Up @@ -858,7 +858,7 @@ struct LocalQueue {
/// The pointer to the state of the executor.
///
/// Used to make sure we don't push runnables to the wrong executor.
state: *const State,
state: usize,

/// The concurrent queue.
queue: Arc<ConcurrentQueue<Runnable>>,
Expand Down Expand Up @@ -889,7 +889,7 @@ impl LocalQueue {
let mut old = with_waker(|waker| {
LOCAL_QUEUE.with(move |slot| {
slot.borrow_mut().replace(LocalQueue {
state: state as *const State,
state: state as *const State as usize,
queue: queue.clone(),
waker: waker.clone(),
})
Expand Down Expand Up @@ -1052,3 +1052,37 @@ fn with_waker<F: FnOnce(&Waker) -> R, R>(f: F) -> impl Future<Output = R> {
Poll::Ready(f(cx.waker()))
})
}

fn _ensure_send_and_sync() {
use futures_lite::future::pending;

fn is_send<T: Send>(_: T) {}
fn is_sync<T: Sync>(_: T) {}

is_send::<Executor<'_>>(Executor::new());
is_sync::<Executor<'_>>(Executor::new());

let ex = Executor::new();
is_send(ex.run(pending::<()>()));
is_sync(ex.run(pending::<()>()));
is_send(ex.tick());
is_sync(ex.tick());

/// ```compile_fail
/// use async_executor::LocalExecutor;
/// use futures_lite::future::pending;
///
/// fn is_send<T: Send>(_: T) {}
/// fn is_sync<T: Sync>(_: T) {}
///
/// is_send::<LocalExecutor<'_>>(LocalExecutor::new());
/// is_sync::<LocalExecutor<'_>>(LocalExecutor::new());
///
/// let ex = LocalExecutor::new();
/// is_send(ex.run(pending::<()>()));
/// is_sync(ex.run(pending::<()>()));
/// is_send(ex.tick());
/// is_sync(ex.tick());
/// ```
fn _negative_test() {}
}

0 comments on commit a5ff8df

Please sign in to comment.