Remove tags
diff --git a/src/header.rs b/src/header.rs
index a559e48..82fcf7c 100644
--- a/src/header.rs
+++ b/src/header.rs
@@ -1,4 +1,3 @@
-use core::alloc::Layout;
use core::cell::UnsafeCell;
use core::fmt;
use core::sync::atomic::{AtomicUsize, Ordering};
@@ -6,7 +5,7 @@
use crate::raw::TaskVTable;
use crate::state::*;
-use crate::utils::{abort_on_panic, extend};
+use crate::utils::abort_on_panic;
/// The header of a task.
///
@@ -158,15 +157,6 @@
abort_on_panic(|| w.wake());
}
}
-
- /// Returns the offset at which the tag of type `T` is stored.
- #[inline]
- pub(crate) fn offset_tag<T>() -> usize {
- let layout_header = Layout::new::<Header>();
- let layout_t = Layout::new::<T>();
- let (_, offset_t) = extend(layout_header, layout_t);
- offset_t
- }
}
impl fmt::Debug for Header {
diff --git a/src/join_handle.rs b/src/join_handle.rs
index edf9fcd..e6dbdb8 100644
--- a/src/join_handle.rs
+++ b/src/join_handle.rs
@@ -15,20 +15,20 @@
///
/// * `None` indicates the task has panicked or was canceled.
/// * `Some(result)` indicates the task has completed with `result` of type `R`.
-pub struct JoinHandle<R, T> {
+pub struct JoinHandle<R> {
/// A raw task pointer.
pub(crate) raw_task: NonNull<()>,
- /// A marker capturing generic types `R` and `T`.
- pub(crate) _marker: PhantomData<(R, T)>,
+ /// A marker capturing generic type `R`.
+ pub(crate) _marker: PhantomData<R>,
}
-unsafe impl<R: Send, T> Send for JoinHandle<R, T> {}
-unsafe impl<R, T> Sync for JoinHandle<R, T> {}
+unsafe impl<R: Send> Send for JoinHandle<R> {}
+unsafe impl<R> Sync for JoinHandle<R> {}
-impl<R, T> Unpin for JoinHandle<R, T> {}
+impl<R> Unpin for JoinHandle<R> {}
-impl<R, T> JoinHandle<R, T> {
+impl<R> JoinHandle<R> {
/// Cancels the task.
///
/// If the task has already completed, calling this method will have no effect.
@@ -81,17 +81,6 @@
}
}
- /// Returns a reference to the tag stored inside the task.
- pub fn tag(&self) -> &T {
- let offset = Header::offset_tag::<T>();
- let ptr = self.raw_task.as_ptr();
-
- unsafe {
- let raw = (ptr as *mut u8).add(offset) as *const T;
- &*raw
- }
- }
-
/// Returns a waker associated with the task.
pub fn waker(&self) -> Waker {
let ptr = self.raw_task.as_ptr();
@@ -104,7 +93,7 @@
}
}
-impl<R, T> Drop for JoinHandle<R, T> {
+impl<R> Drop for JoinHandle<R> {
fn drop(&mut self) {
let ptr = self.raw_task.as_ptr();
let header = ptr as *const Header;
@@ -185,7 +174,7 @@
}
}
-impl<R, T> Future for JoinHandle<R, T> {
+impl<R> Future for JoinHandle<R> {
type Output = Option<R>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
@@ -266,7 +255,7 @@
}
}
-impl<R, T> fmt::Debug for JoinHandle<R, T> {
+impl<R> fmt::Debug for JoinHandle<R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ptr = self.raw_task.as_ptr();
let header = ptr as *const Header;
diff --git a/src/lib.rs b/src/lib.rs
index 3e3cbf6..94afa65 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -39,9 +39,6 @@
//! task.schedule();
//! ```
//!
-//! The last argument to the [`spawn`] function is a *tag*, an arbitrary piece of data associated
-//! with the task. In most executors, this is typically a task identifier or task-local storage.
-//!
//! The function returns a runnable [`Task`] and a [`JoinHandle`] that can await the result.
//!
//! # Execution
diff --git a/src/raw.rs b/src/raw.rs
index 05891d7..0ac0631 100644
--- a/src/raw.rs
+++ b/src/raw.rs
@@ -1,7 +1,6 @@
use alloc::alloc::Layout;
use core::cell::UnsafeCell;
use core::future::Future;
-use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop};
use core::pin::Pin;
use core::ptr::NonNull;
@@ -48,9 +47,6 @@
/// Memory layout of the whole task.
pub(crate) layout: Layout,
- /// Offset into the task at which the tag is stored.
- pub(crate) offset_t: usize,
-
/// Offset into the task at which the schedule function is stored.
pub(crate) offset_s: usize,
@@ -62,16 +58,13 @@
}
/// Raw pointers to the fields inside a task.
-pub(crate) struct RawTask<F, R, S, T> {
+pub(crate) struct RawTask<F, R, S> {
/// The task header.
pub(crate) header: *const Header,
/// The schedule function.
pub(crate) schedule: *const S,
- /// The tag inside the task.
- pub(crate) tag: *mut T,
-
/// The future.
pub(crate) future: *mut F,
@@ -79,18 +72,18 @@
pub(crate) output: *mut R,
}
-impl<F, R, S, T> Copy for RawTask<F, R, S, T> {}
+impl<F, R, S> Copy for RawTask<F, R, S> {}
-impl<F, R, S, T> Clone for RawTask<F, R, S, T> {
+impl<F, R, S> Clone for RawTask<F, R, S> {
fn clone(&self) -> Self {
*self
}
}
-impl<F, R, S, T> RawTask<F, R, S, T>
+impl<F, R, S> RawTask<F, R, S>
where
F: Future<Output = R> + 'static,
- S: Fn(Task<T>) + Send + Sync + 'static,
+ S: Fn(Task) + Send + Sync + 'static,
{
const RAW_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
Self::clone_waker,
@@ -102,7 +95,7 @@
/// Allocates a task with the given `future` and `schedule` function.
///
/// It is assumed that initially only the `Task` reference and the `JoinHandle` exist.
- pub(crate) fn allocate(future: F, schedule: S, tag: T) -> NonNull<()> {
+ pub(crate) fn allocate(future: F, schedule: S) -> NonNull<()> {
// Compute the layout of the task for allocation. Abort if the computation fails.
let task_layout = abort_on_panic(|| Self::task_layout());
@@ -130,9 +123,6 @@
},
});
- // Write the tag as the second field of the task.
- (raw.tag as *mut T).write(tag);
-
// Write the schedule function as the third field of the task.
(raw.schedule as *mut S).write(schedule);
@@ -152,7 +142,6 @@
unsafe {
Self {
header: p as *const Header,
- tag: p.add(task_layout.offset_t) as *mut T,
schedule: p.add(task_layout.offset_s) as *const S,
future: p.add(task_layout.offset_f) as *mut F,
output: p.add(task_layout.offset_r) as *mut R,
@@ -163,9 +152,8 @@
/// Returns the memory layout for a task.
#[inline]
fn task_layout() -> TaskLayout {
- // Compute the layouts for `Header`, `T`, `S`, `F`, and `R`.
+ // Compute the layouts for `Header`, `S`, `F`, and `R`.
let layout_header = Layout::new::<Header>();
- let layout_t = Layout::new::<T>();
let layout_s = Layout::new::<S>();
let layout_f = Layout::new::<F>();
let layout_r = Layout::new::<R>();
@@ -175,9 +163,8 @@
let align_union = layout_f.align().max(layout_r.align());
let layout_union = unsafe { Layout::from_size_align_unchecked(size_union, align_union) };
- // Compute the layout for `Header` followed by `T`, then `S`, and finally `union { F, R }`.
+ // Compute the layout for `Header` followed `S` and `union { F, R }`.
let layout = layout_header;
- let (layout, offset_t) = extend(layout, layout_t);
let (layout, offset_s) = extend(layout, layout_s);
let (layout, offset_union) = extend(layout, layout_union);
let offset_f = offset_union;
@@ -185,7 +172,6 @@
TaskLayout {
layout,
- offset_t,
offset_s,
offset_f,
offset_r,
@@ -311,7 +297,6 @@
// still alive.
let task = Task {
raw_task: NonNull::new_unchecked(ptr as *mut ()),
- _marker: PhantomData,
};
(*raw.schedule)(task);
}
@@ -403,7 +388,6 @@
let task = Task {
raw_task: NonNull::new_unchecked(ptr as *mut ()),
- _marker: PhantomData,
};
(*raw.schedule)(task);
}
@@ -427,7 +411,7 @@
/// Cleans up task's resources and deallocates it.
///
- /// The schedule function and the tag will be dropped, and the task will then get deallocated.
+ /// The schedule function will be dropped, and the task will then get deallocated.
/// The task must be closed before this function is called.
#[inline]
unsafe fn destroy(ptr: *const ()) {
@@ -438,9 +422,6 @@
abort_on_panic(|| {
// Drop the schedule function.
(raw.schedule as *mut S).drop_in_place();
-
- // Drop the tag.
- (raw.tag as *mut T).drop_in_place();
});
// Finally, deallocate the memory reserved by the task.
@@ -609,15 +590,15 @@
return false;
/// A guard that closes the task if polling its future panics.
- struct Guard<F, R, S, T>(RawTask<F, R, S, T>)
+ struct Guard<F, R, S>(RawTask<F, R, S>)
where
F: Future<Output = R> + 'static,
- S: Fn(Task<T>) + Send + Sync + 'static;
+ S: Fn(Task) + Send + Sync + 'static;
- impl<F, R, S, T> Drop for Guard<F, R, S, T>
+ impl<F, R, S> Drop for Guard<F, R, S>
where
F: Future<Output = R> + 'static,
- S: Fn(Task<T>) + Send + Sync + 'static,
+ S: Fn(Task) + Send + Sync + 'static,
{
fn drop(&mut self) {
let raw = self.0;
@@ -632,7 +613,7 @@
if state & CLOSED != 0 {
// The thread that closed the task didn't drop the future because it
// was running so now it's our responsibility to do so.
- RawTask::<F, R, S, T>::drop_future(ptr);
+ RawTask::<F, R, S>::drop_future(ptr);
// Mark the task as not running and not scheduled.
(*raw.header)
@@ -645,7 +626,7 @@
}
// Drop the task reference.
- RawTask::<F, R, S, T>::drop_task(ptr);
+ RawTask::<F, R, S>::drop_task(ptr);
break;
}
@@ -658,7 +639,7 @@
) {
Ok(state) => {
// Drop the future because the task is now closed.
- RawTask::<F, R, S, T>::drop_future(ptr);
+ RawTask::<F, R, S>::drop_future(ptr);
// Notify the awaiter that the future has been dropped.
if state & AWAITER != 0 {
@@ -666,7 +647,7 @@
}
// Drop the task reference.
- RawTask::<F, R, S, T>::drop_task(ptr);
+ RawTask::<F, R, S>::drop_task(ptr);
break;
}
Err(s) => state = s,
diff --git a/src/task.rs b/src/task.rs
index 4d60f07..6fb4cad 100644
--- a/src/task.rs
+++ b/src/task.rs
@@ -17,7 +17,7 @@
/// awaits its result.
///
/// When run, the task polls `future`. When woken up, it gets scheduled for running by the
-/// `schedule` function. Argument `tag` is an arbitrary piece of data stored inside the task.
+/// `schedule` function.
///
/// The schedule function should not attempt to run the task nor to drop it. Instead, it should
/// push the task into some kind of queue so that it can be processed later.
@@ -47,24 +47,22 @@
/// // Create a task with the future and the schedule function.
/// let (task, handle) = async_task::spawn(future, schedule, ());
/// ```
-pub fn spawn<F, R, S, T>(future: F, schedule: S, tag: T) -> (Task<T>, JoinHandle<R, T>)
+pub fn spawn<F, R, S>(future: F, schedule: S) -> (Task, JoinHandle<R>)
where
F: Future<Output = R> + Send + 'static,
R: Send + 'static,
- S: Fn(Task<T>) + Send + Sync + 'static,
- T: Send + Sync + 'static,
+ S: Fn(Task) + Send + Sync + 'static,
{
// Allocate large futures on the heap.
let raw_task = if mem::size_of::<F>() >= 2048 {
let future = alloc::boxed::Box::pin(future);
- RawTask::<_, R, S, T>::allocate(future, schedule, tag)
+ RawTask::<_, R, S>::allocate(future, schedule)
} else {
- RawTask::<F, R, S, T>::allocate(future, schedule, tag)
+ RawTask::<F, R, S>::allocate(future, schedule)
};
let task = Task {
raw_task,
- _marker: PhantomData,
};
let handle = JoinHandle {
raw_task,
@@ -79,7 +77,7 @@
/// awaits its result.
///
/// When run, the task polls `future`. When woken up, it gets scheduled for running by the
-/// `schedule` function. Argument `tag` is an arbitrary piece of data stored inside the task.
+/// `schedule` function.
///
/// The schedule function should not attempt to run the task nor to drop it. Instead, it should
/// push the task into some kind of queue so that it can be processed later.
@@ -113,12 +111,11 @@
/// let (task, handle) = async_task::spawn_local(future, schedule, ());
/// ```
#[cfg(feature = "std")]
-pub fn spawn_local<F, R, S, T>(future: F, schedule: S, tag: T) -> (Task<T>, JoinHandle<R, T>)
+pub fn spawn_local<F, R, S>(future: F, schedule: S) -> (Task, JoinHandle<R>)
where
F: Future<Output = R> + 'static,
R: 'static,
- S: Fn(Task<T>) + Send + Sync + 'static,
- T: Send + Sync + 'static,
+ S: Fn(Task) + Send + Sync + 'static,
{
extern crate std;
@@ -175,14 +172,13 @@
// Allocate large futures on the heap.
let raw_task = if mem::size_of::<F>() >= 2048 {
let future = alloc::boxed::Box::pin(future);
- RawTask::<_, R, S, T>::allocate(future, schedule, tag)
+ RawTask::<_, R, S>::allocate(future, schedule)
} else {
- RawTask::<_, R, S, T>::allocate(future, schedule, tag)
+ RawTask::<_, R, S>::allocate(future, schedule)
};
let task = Task {
raw_task,
- _marker: PhantomData,
};
let handle = JoinHandle {
raw_task,
@@ -211,18 +207,15 @@
/// [`JoinHandle`]: struct.JoinHandle.html
/// [`Task`]: struct.Task.html
/// [`Waker`]: https://doc.rust-lang.org/std/task/struct.Waker.html
-pub struct Task<T> {
+pub struct Task {
/// A pointer to the heap-allocated task.
pub(crate) raw_task: NonNull<()>,
-
- /// A marker capturing the generic type `T`.
- pub(crate) _marker: PhantomData<T>,
}
-unsafe impl<T> Send for Task<T> {}
-unsafe impl<T> Sync for Task<T> {}
+unsafe impl Send for Task {}
+unsafe impl Sync for Task {}
-impl<T> Task<T> {
+impl Task {
/// Schedules the task.
///
/// This is a convenience method that simply reschedules the task by passing it to its schedule
@@ -280,38 +273,21 @@
}
}
- /// Returns a reference to the tag stored inside the task.
- pub fn tag(&self) -> &T {
- let offset = Header::offset_tag::<T>();
- let ptr = self.raw_task.as_ptr();
-
- unsafe {
- let raw = (ptr as *mut u8).add(offset) as *const T;
- &*raw
- }
- }
-
- /// Converts this task into a raw pointer to the tag.
- pub fn into_raw(self) -> *const T {
- let offset = Header::offset_tag::<T>();
+ /// Converts this task into a raw pointer.
+ pub fn into_raw(self) -> *mut () {
let ptr = self.raw_task.as_ptr();
mem::forget(self);
-
- unsafe { (ptr as *mut u8).add(offset) as *const T }
+ ptr
}
- /// Converts a raw pointer to the tag into a task.
+ /// Converts a raw pointer into a task.
///
/// This method should only be used with raw pointers returned from [`into_raw`].
///
/// [`into_raw`]: #method.into_raw
- pub unsafe fn from_raw(raw: *const T) -> Task<T> {
- let offset = Header::offset_tag::<T>();
- let ptr = (raw as *mut u8).sub(offset) as *mut ();
-
+ pub unsafe fn from_raw(raw: *mut ()) -> Task {
Task {
- raw_task: NonNull::new_unchecked(ptr),
- _marker: PhantomData,
+ raw_task: NonNull::new_unchecked(raw as *mut ()),
}
}
@@ -327,7 +303,7 @@
}
}
-impl<T> Drop for Task<T> {
+impl Drop for Task {
fn drop(&mut self) {
let ptr = self.raw_task.as_ptr();
let header = ptr as *const Header;
@@ -353,14 +329,13 @@
}
}
-impl<T: fmt::Debug> fmt::Debug for Task<T> {
+impl fmt::Debug for Task {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ptr = self.raw_task.as_ptr();
let header = ptr as *const Header;
f.debug_struct("Task")
.field("header", unsafe { &(*header) })
- .field("tag", self.tag())
.finish()
}
}