Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/runnable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,32 @@ impl<M> Runnable<M> {
&self.header_with_metadata().metadata
}

/// Returns `true` if the [`Task`] handle has been dropped or cancelled.
///
/// # Examples
///
/// ```
/// // A function that schedules the task when it gets woken up.
/// let (s, r) = flume::unbounded();
/// let schedule = move |runnable| s.send(runnable).unwrap();
///
/// // Create a task with a simple future and the schedule function.
/// let (runnable, task) = async_task::spawn(async { 1 + 2 }, schedule);
///
/// // The task is not cancelled initially.
/// assert!(!runnable.is_cancelled());
///
/// // Drop the `Task` handle to cancel the task.
/// drop(task);
///
/// // The task is now cancelled.
/// assert!(runnable.is_cancelled());
/// # runnable.run();
/// ```
pub fn is_cancelled(&self) -> bool {
self.header().state.load(Ordering::Acquire) & CLOSED != 0
}

/// Schedules the task.
///
/// This is a convenience method that passes the [`Runnable`] to the schedule function.
Expand Down
24 changes: 24 additions & 0 deletions tests/is_cancelled.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use std::pin::pin;

use smol::future;

#[test]
fn cancelled_after_task_drop() {
let f = async {};
let (runnable, task) = async_task::spawn(f, |_| {});
assert!(!runnable.is_cancelled());
drop(task);
assert!(runnable.is_cancelled());
}

#[test]
fn cancelled_after_task_cancel() {
let f = async {};
let (runnable, task) = async_task::spawn(f, |_| {});

assert!(!runnable.is_cancelled());

let mut cancel_fut = pin!(task.cancel());
assert!(future::block_on(future::poll_once(&mut cancel_fut)).is_none());
assert!(runnable.is_cancelled());
}