Skip to content

Commit

Permalink
Add docs and fix warning in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
osiewicz committed Dec 20, 2023
1 parent 17fdfc6 commit 31a4d35
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 4 deletions.
57 changes: 54 additions & 3 deletions src/runnable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,18 +822,69 @@ impl<M> Runnable<M> {
}

/// Converts this task into a raw pointer.
///
/// To avoid a memory leak the pointer must be converted back to a Runnable using [`Runnable<M>::from_raw`][from_raw].
///
/// `into_raw` does not change the state of the [`Task`], but there is no guarantee that it will be in the same state after calling [`Runnable<M>::from_raw`][from_raw],
/// as the corresponding [`Task`] might have been dropped or cancelled.
///
/// # Examples
///
/// ```rust
/// use async_task::{Runnable, spawn};

/// let (runnable, task) = spawn(async {}, |_| {});
/// let runnable_pointer = runnable.into_raw();
///
/// unsafe {
/// // Convert back to an `Runnable` to prevent leak.
/// let runnable = Runnable::<()>::from_raw(runnable_pointer);
/// let did_poll = runnable.run();
/// assert!(did_poll);
/// // Further calls to `Runnable::from_raw(runnable_pointer)` would be memory-unsafe.
/// }
/// // The memory was freed when `x` went out of scope above, so `runnable_pointer` is now dangling!
/// ```
/// [from_raw]: #method.from_raw
pub fn into_raw(self) -> NonNull<()> {
let ptr = self.ptr;
mem::forget(self);
ptr
}

/// Converts a raw pointer into a task.
/// Converts a raw pointer into a Runnable.
///
/// # Safety
/// This method should only be used with raw pointers returned from [`into_raw`].
///
/// [`into_raw`]: #method.into_raw
/// This method should only be used with raw pointers returned from [`Runnable<M>::into_raw`][into_raw].
/// It is not safe to use the provided pointer once it is passed to `from_raw`.
/// Crucially, it is unsafe to call `from_raw` multiple times with the same pointer - even if the resulting [`Runnable`] is not used -
/// as internally `async-task` uses reference counting.
///
/// It is however safe to call [`Runnable<M>::into_raw`][into_raw] on a [`Runnable`] created with `from_raw` or
/// after the [`Task`] associated with a given Runnable has been dropped or cancelled.
///
/// The state of the [`Runnable`] created with `from_raw` is not specified.
/// # Examples
///
/// ```rust
/// use async_task::{Runnable, spawn};

/// let (runnable, task) = spawn(async {}, |_| {});
/// let runnable_pointer = runnable.into_raw();
///
/// drop(task);
/// unsafe {
/// // Convert back to an `Runnable` to prevent leak.
/// let runnable = Runnable::<()>::from_raw(runnable_pointer);
/// let did_poll = runnable.run();
/// assert!(!did_poll);
/// // Further calls to `Runnable::from_raw(runnable_pointer)` would be memory-unsafe.
/// }
/// // The memory was freed when `x` went out of scope above, so `runnable_pointer` is now dangling!
/// ```

/// [into_raw]: #method.into_raw
pub unsafe fn from_raw(ptr: NonNull<()>) -> Self {
Self {
ptr,
Expand Down
2 changes: 1 addition & 1 deletion tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ fn raw() {
task.run();
}

let mut task_got_executed = Arc::new(AtomicBool::new(false));
let task_got_executed = Arc::new(AtomicBool::new(false));
let (runnable, _handle) = async_task::spawn(
{
let task_got_executed = task_got_executed.clone();
Expand Down

0 comments on commit 31a4d35

Please sign in to comment.