Skip to content

Commit 433e6b3

Browse files
Add LocalTaskObj
1 parent 1f9aa13 commit 433e6b3

File tree

4 files changed

+118
-8
lines changed

4 files changed

+118
-8
lines changed

src/liballoc/boxed.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use core::marker::{Unpin, Unsize};
6666
use core::mem::{self, PinMut};
6767
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
6868
use core::ptr::{self, NonNull, Unique};
69-
use core::task::{Context, Poll, UnsafeTask, TaskObj};
69+
use core::task::{Context, Poll, UnsafeTask, TaskObj, LocalTaskObj};
7070
use core::convert::From;
7171

7272
use raw_vec::RawVec;
@@ -933,7 +933,7 @@ impl<'a, F: ?Sized + Future> Future for PinBox<F> {
933933
}
934934

935935
#[unstable(feature = "futures_api", issue = "50547")]
936-
unsafe impl<F: Future<Output = ()> + Send + 'static> UnsafeTask for PinBox<F> {
936+
unsafe impl<F: Future<Output = ()> + 'static> UnsafeTask for PinBox<F> {
937937
fn into_raw(self) -> *mut () {
938938
PinBox::into_raw(self) as *mut ()
939939
}
@@ -962,3 +962,17 @@ impl<F: Future<Output = ()> + Send + 'static> From<Box<F>> for TaskObj {
962962
TaskObj::new(PinBox::from(boxed))
963963
}
964964
}
965+
966+
#[unstable(feature = "futures_api", issue = "50547")]
967+
impl<F: Future<Output = ()> + 'static> From<PinBox<F>> for LocalTaskObj {
968+
fn from(boxed: PinBox<F>) -> Self {
969+
LocalTaskObj::new(boxed)
970+
}
971+
}
972+
973+
#[unstable(feature = "futures_api", issue = "50547")]
974+
impl<F: Future<Output = ()> + 'static> From<Box<F>> for LocalTaskObj {
975+
fn from(boxed: Box<F>) -> Self {
976+
LocalTaskObj::new(PinBox::from(boxed))
977+
}
978+
}

src/libcore/task/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ mod poll;
2424
pub use self::poll::Poll;
2525

2626
mod spawn_error;
27-
pub use self::spawn_error::{SpawnErrorKind, SpawnObjError};
27+
pub use self::spawn_error::{SpawnErrorKind, SpawnObjError, SpawnLocalObjError};
2828

2929
mod task;
30-
pub use self::task::{TaskObj, UnsafeTask};
30+
pub use self::task::{TaskObj, LocalTaskObj, UnsafeTask};
3131

3232
mod wake;
3333
pub use self::wake::{Waker, LocalWaker, UnsafeWake};

src/libcore/task/spawn_error.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
issue = "50547")]
1414

1515
use fmt;
16-
use super::TaskObj;
16+
use mem;
17+
use super::{TaskObj, LocalTaskObj};
1718

1819
/// Provides the reason that an executor was unable to spawn.
1920
pub struct SpawnErrorKind {
@@ -49,3 +50,33 @@ pub struct SpawnObjError {
4950
/// The task for which spawning was attempted
5051
pub task: TaskObj,
5152
}
53+
54+
/// The result of a failed spawn
55+
#[derive(Debug)]
56+
pub struct SpawnLocalObjError {
57+
/// The kind of error
58+
pub kind: SpawnErrorKind,
59+
60+
/// The task for which spawning was attempted
61+
pub task: LocalTaskObj,
62+
}
63+
64+
impl SpawnLocalObjError {
65+
/// Converts the `SpawnLocalObjError` into a `SpawnObjError`
66+
/// To make this operation safe one has to ensure that the `UnsafeTask`
67+
/// instance from which the `LocalTaskObj` stored inside was created
68+
/// actually implements `Send`.
69+
pub unsafe fn as_spawn_obj_error(self) -> SpawnObjError {
70+
// Safety: Both structs have the same memory layout
71+
mem::transmute::<SpawnLocalObjError, SpawnObjError>(self)
72+
}
73+
}
74+
75+
impl From<SpawnObjError> for SpawnLocalObjError {
76+
fn from(error: SpawnObjError) -> SpawnLocalObjError {
77+
unsafe {
78+
// Safety: Both structs have the same memory layout
79+
mem::transmute::<SpawnObjError, SpawnLocalObjError>(error)
80+
}
81+
}
82+
}

src/libcore/task/task.rs

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use fmt;
1616
use future::Future;
17-
use mem::PinMut;
17+
use mem::{self, PinMut};
1818
use super::{Context, Poll};
1919

2020
/// A custom trait object for polling tasks, roughly akin to
@@ -30,7 +30,7 @@ unsafe impl Send for TaskObj {}
3030
impl TaskObj {
3131
/// Create a `TaskObj` from a custom trait object representation.
3232
#[inline]
33-
pub fn new<T: UnsafeTask>(t: T) -> TaskObj {
33+
pub fn new<T: UnsafeTask + Send>(t: T) -> TaskObj {
3434
TaskObj {
3535
ptr: t.into_raw(),
3636
poll_fn: T::poll,
@@ -65,6 +65,71 @@ impl Drop for TaskObj {
6565
}
6666
}
6767

68+
/// A custom trait object for polling tasks, roughly akin to
69+
/// `Box<Future<Output = ()>>`.
70+
/// Contrary to `TaskObj`, `LocalTaskObj` does not have a `Send` bound.
71+
pub struct LocalTaskObj {
72+
ptr: *mut (),
73+
poll_fn: unsafe fn(*mut (), &mut Context) -> Poll<()>,
74+
drop_fn: unsafe fn(*mut ()),
75+
}
76+
77+
impl LocalTaskObj {
78+
/// Create a `LocalTaskObj` from a custom trait object representation.
79+
#[inline]
80+
pub fn new<T: UnsafeTask>(t: T) -> LocalTaskObj {
81+
LocalTaskObj {
82+
ptr: t.into_raw(),
83+
poll_fn: T::poll,
84+
drop_fn: T::drop,
85+
}
86+
}
87+
88+
/// Converts the `LocalTaskObj` into a `TaskObj`
89+
/// To make this operation safe one has to ensure that the `UnsafeTask`
90+
/// instance from which this `LocalTaskObj` was created actually implements
91+
/// `Send`.
92+
pub unsafe fn as_task_obj(self) -> TaskObj {
93+
// Safety: Both structs have the same memory layout
94+
mem::transmute::<LocalTaskObj, TaskObj>(self)
95+
}
96+
}
97+
98+
impl fmt::Debug for LocalTaskObj {
99+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100+
f.debug_struct("LocalTaskObj")
101+
.finish()
102+
}
103+
}
104+
105+
impl From<TaskObj> for LocalTaskObj {
106+
fn from(task: TaskObj) -> LocalTaskObj {
107+
unsafe {
108+
// Safety: Both structs have the same memory layout
109+
mem::transmute::<TaskObj, LocalTaskObj>(task)
110+
}
111+
}
112+
}
113+
114+
impl Future for LocalTaskObj {
115+
type Output = ();
116+
117+
#[inline]
118+
fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
119+
unsafe {
120+
(self.poll_fn)(self.ptr, cx)
121+
}
122+
}
123+
}
124+
125+
impl Drop for LocalTaskObj {
126+
fn drop(&mut self) {
127+
unsafe {
128+
(self.drop_fn)(self.ptr)
129+
}
130+
}
131+
}
132+
68133
/// A custom implementation of a task trait object for `TaskObj`, providing
69134
/// a hand-rolled vtable.
70135
///
@@ -74,7 +139,7 @@ impl Drop for TaskObj {
74139
/// The implementor must guarantee that it is safe to call `poll` repeatedly (in
75140
/// a non-concurrent fashion) with the result of `into_raw` until `drop` is
76141
/// called.
77-
pub unsafe trait UnsafeTask: Send + 'static {
142+
pub unsafe trait UnsafeTask: 'static {
78143
/// Convert a owned instance into a (conceptually owned) void pointer.
79144
fn into_raw(self) -> *mut ();
80145

0 commit comments

Comments
 (0)