Nested LocalTaskObj in TaskObj, remove SpawnErrorObj conversions

This commit is contained in:
Josef Reinhard Brandl 2018-06-26 21:06:20 +02:00
parent 433e6b31a7
commit c055fef010
2 changed files with 34 additions and 75 deletions

View File

@ -60,23 +60,3 @@ pub struct SpawnLocalObjError {
/// The task for which spawning was attempted
pub task: LocalTaskObj,
}
impl SpawnLocalObjError {
/// Converts the `SpawnLocalObjError` into a `SpawnObjError`
/// To make this operation safe one has to ensure that the `UnsafeTask`
/// instance from which the `LocalTaskObj` stored inside was created
/// actually implements `Send`.
pub unsafe fn as_spawn_obj_error(self) -> SpawnObjError {
// Safety: Both structs have the same memory layout
mem::transmute::<SpawnLocalObjError, SpawnObjError>(self)
}
}
impl From<SpawnObjError> for SpawnLocalObjError {
fn from(error: SpawnObjError) -> SpawnLocalObjError {
unsafe {
// Safety: Both structs have the same memory layout
mem::transmute::<SpawnObjError, SpawnLocalObjError>(error)
}
}
}

View File

@ -14,57 +14,9 @@
use fmt;
use future::Future;
use mem::{self, PinMut};
use mem::PinMut;
use super::{Context, Poll};
/// A custom trait object for polling tasks, roughly akin to
/// `Box<Future<Output = ()> + Send>`.
pub struct TaskObj {
ptr: *mut (),
poll_fn: unsafe fn(*mut (), &mut Context) -> Poll<()>,
drop_fn: unsafe fn(*mut ()),
}
unsafe impl Send for TaskObj {}
impl TaskObj {
/// Create a `TaskObj` from a custom trait object representation.
#[inline]
pub fn new<T: UnsafeTask + Send>(t: T) -> TaskObj {
TaskObj {
ptr: t.into_raw(),
poll_fn: T::poll,
drop_fn: T::drop,
}
}
}
impl fmt::Debug for TaskObj {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TaskObj")
.finish()
}
}
impl Future for TaskObj {
type Output = ();
#[inline]
fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
unsafe {
(self.poll_fn)(self.ptr, cx)
}
}
}
impl Drop for TaskObj {
fn drop(&mut self) {
unsafe {
(self.drop_fn)(self.ptr)
}
}
}
/// A custom trait object for polling tasks, roughly akin to
/// `Box<Future<Output = ()>>`.
/// Contrary to `TaskObj`, `LocalTaskObj` does not have a `Send` bound.
@ -90,8 +42,7 @@ impl LocalTaskObj {
/// instance from which this `LocalTaskObj` was created actually implements
/// `Send`.
pub unsafe fn as_task_obj(self) -> TaskObj {
// Safety: Both structs have the same memory layout
mem::transmute::<LocalTaskObj, TaskObj>(self)
TaskObj(self)
}
}
@ -104,10 +55,7 @@ impl fmt::Debug for LocalTaskObj {
impl From<TaskObj> for LocalTaskObj {
fn from(task: TaskObj) -> LocalTaskObj {
unsafe {
// Safety: Both structs have the same memory layout
mem::transmute::<TaskObj, LocalTaskObj>(task)
}
task.0
}
}
@ -130,6 +78,37 @@ impl Drop for LocalTaskObj {
}
}
/// A custom trait object for polling tasks, roughly akin to
/// `Box<Future<Output = ()> + Send>`.
pub struct TaskObj(LocalTaskObj);
unsafe impl Send for TaskObj {}
impl TaskObj {
/// Create a `TaskObj` from a custom trait object representation.
#[inline]
pub fn new<T: UnsafeTask + Send>(t: T) -> TaskObj {
TaskObj(LocalTaskObj::new(t))
}
}
impl fmt::Debug for TaskObj {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TaskObj")
.finish()
}
}
impl Future for TaskObj {
type Output = ();
#[inline]
fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
pinned_field.poll(cx)
}
}
/// A custom implementation of a task trait object for `TaskObj`, providing
/// a hand-rolled vtable.
///