Skip to content

Commit a201b91

Browse files
committed
assign IDs sequentially instead of by addr
Signed-off-by: Eliza Weisman <[email protected]>
1 parent a332b7a commit a201b91

File tree

6 files changed

+43
-49
lines changed

6 files changed

+43
-49
lines changed

tokio/src/runtime/task/abort.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::runtime::task::RawTask;
1+
use crate::runtime::task::{Id, RawTask};
22
use std::fmt;
33
use std::panic::{RefUnwindSafe, UnwindSafe};
44

@@ -21,11 +21,12 @@ use std::panic::{RefUnwindSafe, UnwindSafe};
2121
#[cfg_attr(not(tokio_unstable), allow(unreachable_pub))]
2222
pub struct AbortHandle {
2323
raw: Option<RawTask>,
24+
id: Id,
2425
}
2526

2627
impl AbortHandle {
27-
pub(super) fn new(raw: Option<RawTask>) -> Self {
28-
Self { raw }
28+
pub(super) fn new(raw: Option<RawTask>, id: Id) -> Self {
29+
Self { raw, id }
2930
}
3031

3132
/// Abort the task associated with the handle.
@@ -60,8 +61,7 @@ impl AbortHandle {
6061
#[cfg(tokio_unstable)]
6162
#[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
6263
pub fn id(&self) -> super::Id {
63-
// XXX(eliza): should this return an option instead? probably not...
64-
self.raw.unwrap().id()
64+
self.id.clone()
6565
}
6666
}
6767

@@ -73,7 +73,9 @@ impl RefUnwindSafe for AbortHandle {}
7373

7474
impl fmt::Debug for AbortHandle {
7575
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
76-
fmt.debug_struct("AbortHandle").finish()
76+
fmt.debug_struct("AbortHandle")
77+
.field("id", &self.id)
78+
.finish()
7779
}
7880
}
7981

tokio/src/runtime/task/core.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::future::Future;
1313
use crate::loom::cell::UnsafeCell;
1414
use crate::runtime::task::raw::{self, Vtable};
1515
use crate::runtime::task::state::State;
16-
use crate::runtime::task::Schedule;
16+
use crate::runtime::task::{Id, Schedule};
1717
use crate::util::linked_list;
1818

1919
use std::pin::Pin;
@@ -49,6 +49,9 @@ pub(super) struct Core<T: Future, S> {
4949

5050
/// Either the future or the output.
5151
pub(super) stage: CoreStage<T>,
52+
53+
/// The task's ID, used for populating `JoinError`s.
54+
pub(super) task_id: Id,
5255
}
5356

5457
/// Crate public as this is also needed by the pool.
@@ -102,7 +105,7 @@ pub(super) enum Stage<T: Future> {
102105
impl<T: Future, S: Schedule> Cell<T, S> {
103106
/// Allocates a new task cell, containing the header, trailer, and core
104107
/// structures.
105-
pub(super) fn new(future: T, scheduler: S, state: State) -> Box<Cell<T, S>> {
108+
pub(super) fn new(future: T, scheduler: S, state: State, task_id: Id) -> Box<Cell<T, S>> {
106109
#[cfg(all(tokio_unstable, feature = "tracing"))]
107110
let id = future.id();
108111
Box::new(Cell {
@@ -120,6 +123,7 @@ impl<T: Future, S: Schedule> Cell<T, S> {
120123
stage: CoreStage {
121124
stage: UnsafeCell::new(Stage::Running(future)),
122125
},
126+
task_id,
123127
},
124128
trailer: Trailer {
125129
waker: UnsafeCell::new(None),

tokio/src/runtime/task/harness.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ where
100100
let header_ptr = self.header_ptr();
101101
let waker_ref = waker_ref::<T, S>(&header_ptr);
102102
let cx = Context::from_waker(&*waker_ref);
103-
let id = super::Id::from_raw(header_ptr);
104-
let res = poll_future(&self.core().stage, id.clone(), cx);
103+
let core = self.core();
104+
let res = poll_future(&core.stage, core.task_id.clone(), cx);
105105

106106
if res == Poll::Ready(()) {
107107
// The future completed. Move on to complete the task.
@@ -115,14 +115,15 @@ where
115115
TransitionToIdle::Cancelled => {
116116
// The transition to idle failed because the task was
117117
// cancelled during the poll.
118-
119-
cancel_task(&self.core().stage, id);
118+
let core = self.core();
119+
cancel_task(&core.stage, core.task_id.clone());
120120
PollFuture::Complete
121121
}
122122
}
123123
}
124124
TransitionToRunning::Cancelled => {
125-
cancel_task(&self.core().stage, super::Id::from_raw(self.header_ptr()));
125+
let core = self.core();
126+
cancel_task(&core.stage, core.task_id.clone());
126127
PollFuture::Complete
127128
}
128129
TransitionToRunning::Failed => PollFuture::Done,
@@ -145,7 +146,8 @@ where
145146

146147
// By transitioning the lifecycle to `Running`, we have permission to
147148
// drop the future.
148-
cancel_task(&self.core().stage, super::Id::from_raw(self.header_ptr()));
149+
let core = self.core();
150+
cancel_task(&core.stage, core.task_id.clone());
149151
self.complete();
150152
}
151153

tokio/src/runtime/task/join.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::runtime::task::RawTask;
1+
use crate::runtime::task::{Id, RawTask};
22

33
use std::fmt;
44
use std::future::Future;
@@ -144,6 +144,7 @@ cfg_rt! {
144144
/// [`JoinError`]: crate::task::JoinError
145145
pub struct JoinHandle<T> {
146146
raw: Option<RawTask>,
147+
id: Id,
147148
_p: PhantomData<T>,
148149
}
149150
}
@@ -155,9 +156,10 @@ impl<T> UnwindSafe for JoinHandle<T> {}
155156
impl<T> RefUnwindSafe for JoinHandle<T> {}
156157

157158
impl<T> JoinHandle<T> {
158-
pub(super) fn new(raw: RawTask) -> JoinHandle<T> {
159+
pub(super) fn new(raw: RawTask, id: Id) -> JoinHandle<T> {
159160
JoinHandle {
160161
raw: Some(raw),
162+
id,
161163
_p: PhantomData,
162164
}
163165
}
@@ -218,7 +220,7 @@ impl<T> JoinHandle<T> {
218220
raw.ref_inc();
219221
raw
220222
});
221-
super::AbortHandle::new(raw)
223+
super::AbortHandle::new(raw, self.id.clone())
222224
}
223225

224226
/// Returns a [task ID] that uniquely identifies this task relative to other
@@ -235,8 +237,7 @@ impl<T> JoinHandle<T> {
235237
#[cfg(tokio_unstable)]
236238
#[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
237239
pub fn id(&self) -> super::Id {
238-
// XXX(eliza): should this return an option instead? probably not...
239-
self.raw.unwrap().id()
240+
self.id.clone()
240241
}
241242
}
242243

@@ -298,6 +299,8 @@ where
298299
T: fmt::Debug,
299300
{
300301
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
301-
fmt.debug_struct("JoinHandle").finish()
302+
fmt.debug_struct("JoinHandle")
303+
.field("id", &self.id)
304+
.finish()
302305
}
303306
}

tokio/src/runtime/task/mod.rs

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ use std::{fmt, mem};
203203
#[cfg_attr(not(tokio_unstable), allow(unreachable_pub))]
204204
// TODO(eliza): there's almost certainly no reason not to make this `Copy` as well...
205205
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
206-
pub struct Id(std::num::NonZeroUsize);
206+
pub struct Id(usize);
207207

208208
/// An owned handle to the task, tracked by ref count.
209209
#[repr(transparent)]
@@ -278,7 +278,8 @@ cfg_rt! {
278278
T: Future + 'static,
279279
T::Output: 'static,
280280
{
281-
let raw = RawTask::new::<T, S>(task, scheduler);
281+
let id = Id::next();
282+
let raw = RawTask::new::<T, S>(task, scheduler, id.clone());
282283
let task = Task {
283284
raw,
284285
_p: PhantomData,
@@ -287,7 +288,7 @@ cfg_rt! {
287288
raw,
288289
_p: PhantomData,
289290
});
290-
let join = JoinHandle::new(raw);
291+
let join = JoinHandle::new(raw, id);
291292

292293
(task, notified, join)
293294
}
@@ -477,25 +478,11 @@ impl fmt::Display for Id {
477478
self.0.fmt(f)
478479
}
479480
}
480-
impl Id {
481-
#[inline]
482-
fn from_raw(ptr: NonNull<Header>) -> Self {
483-
use std::num::NonZeroUsize;
484-
let addr = ptr.as_ptr() as usize;
485-
486-
#[cfg(debug_assertions)]
487-
let inner = NonZeroUsize::new(addr)
488-
.expect("a `NonNull` pointer will never be 0 when cast to `usize`");
489-
490-
#[cfg(not(debug_assertions))]
491-
let inner = unsafe {
492-
// Safety: `addr` was cast from a `NonNull` pointer, which must
493-
// never be null (0). Since the pointer is not null, the integer
494-
// will never be zero, so this is safe as long as the `NonNull` was
495-
// constructed safely.
496-
NonZeroUsize::new_unchecked(addr)
497-
};
498481

499-
Self(inner)
482+
impl Id {
483+
fn next() -> Self {
484+
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
485+
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
486+
Self(NEXT_ID.fetch_add(1, Relaxed))
500487
}
501488
}

tokio/src/runtime/task/raw.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::future::Future;
2-
use crate::runtime::task::{Cell, Harness, Header, Schedule, State};
2+
use crate::runtime::task::{Cell, Harness, Header, Id, Schedule, State};
33

44
use std::ptr::NonNull;
55
use std::task::{Poll, Waker};
@@ -52,12 +52,12 @@ pub(super) fn vtable<T: Future, S: Schedule>() -> &'static Vtable {
5252
}
5353

5454
impl RawTask {
55-
pub(super) fn new<T, S>(task: T, scheduler: S) -> RawTask
55+
pub(super) fn new<T, S>(task: T, scheduler: S, id: Id) -> RawTask
5656
where
5757
T: Future,
5858
S: Schedule,
5959
{
60-
let ptr = Box::into_raw(Cell::<_, S>::new(task, scheduler, State::new()));
60+
let ptr = Box::into_raw(Cell::<_, S>::new(task, scheduler, State::new(), id));
6161
let ptr = unsafe { NonNull::new_unchecked(ptr as *mut Header) };
6262

6363
RawTask { ptr }
@@ -129,10 +129,6 @@ impl RawTask {
129129
pub(super) fn ref_inc(self) {
130130
self.header().state.ref_inc();
131131
}
132-
133-
pub(super) fn id(&self) -> super::Id {
134-
super::Id::from_raw(self.ptr)
135-
}
136132
}
137133

138134
impl Clone for RawTask {

0 commit comments

Comments
 (0)