about summary refs log tree commit diff
path: root/src/libcore/task
diff options
context:
space:
mode:
authorJosef Reinhard Brandl <mail@josefbrandl.de>2018-06-26 17:06:20 +0200
committerJosef Reinhard Brandl <mail@josefbrandl.de>2018-06-26 17:06:20 +0200
commit433e6b31a75eea5ce45493acc63eae462d740338 (patch)
tree74971086254a1d533d177ec8848050bed679230a /src/libcore/task
parent1f9aa1332fc9f0194bac1761ef04e54564e26fc8 (diff)
downloadrust-433e6b31a75eea5ce45493acc63eae462d740338.tar.gz
rust-433e6b31a75eea5ce45493acc63eae462d740338.zip
Add `LocalTaskObj`
Diffstat (limited to 'src/libcore/task')
-rw-r--r--src/libcore/task/mod.rs4
-rw-r--r--src/libcore/task/spawn_error.rs33
-rw-r--r--src/libcore/task/task.rs71
3 files changed, 102 insertions, 6 deletions
diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs
index 66ab21d177d..36370b6b37c 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -24,10 +24,10 @@ mod poll;
 pub use self::poll::Poll;
 
 mod spawn_error;
-pub use self::spawn_error::{SpawnErrorKind, SpawnObjError};
+pub use self::spawn_error::{SpawnErrorKind, SpawnObjError, SpawnLocalObjError};
 
 mod task;
-pub use self::task::{TaskObj, UnsafeTask};
+pub use self::task::{TaskObj, LocalTaskObj, UnsafeTask};
 
 mod wake;
 pub use self::wake::{Waker, LocalWaker, UnsafeWake};
diff --git a/src/libcore/task/spawn_error.rs b/src/libcore/task/spawn_error.rs
index 5dd9c5be689..57bb9ebeb30 100644
--- a/src/libcore/task/spawn_error.rs
+++ b/src/libcore/task/spawn_error.rs
@@ -13,7 +13,8 @@
             issue = "50547")]
 
 use fmt;
-use super::TaskObj;
+use mem;
+use super::{TaskObj, LocalTaskObj};
 
 /// Provides the reason that an executor was unable to spawn.
 pub struct SpawnErrorKind {
@@ -49,3 +50,33 @@ pub struct SpawnObjError {
     /// The task for which spawning was attempted
     pub task: TaskObj,
 }
+
+/// The result of a failed spawn
+#[derive(Debug)]
+pub struct SpawnLocalObjError {
+    /// The kind of error
+    pub kind: SpawnErrorKind,
+
+    /// 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)
+        }
+    }
+}
diff --git a/src/libcore/task/task.rs b/src/libcore/task/task.rs
index dc4ff314e5b..9896d7f5ff2 100644
--- a/src/libcore/task/task.rs
+++ b/src/libcore/task/task.rs
@@ -14,7 +14,7 @@
 
 use fmt;
 use future::Future;
-use mem::PinMut;
+use mem::{self, PinMut};
 use super::{Context, Poll};
 
 /// A custom trait object for polling tasks, roughly akin to
@@ -30,7 +30,7 @@ unsafe impl Send for TaskObj {}
 impl TaskObj {
     /// Create a `TaskObj` from a custom trait object representation.
     #[inline]
-    pub fn new<T: UnsafeTask>(t: T) -> TaskObj {
+    pub fn new<T: UnsafeTask + Send>(t: T) -> TaskObj {
         TaskObj {
             ptr: t.into_raw(),
             poll_fn: T::poll,
@@ -65,6 +65,71 @@ impl Drop for TaskObj {
     }
 }
 
+/// A custom trait object for polling tasks, roughly akin to
+/// `Box<Future<Output = ()>>`.
+/// Contrary to `TaskObj`, `LocalTaskObj` does not have a `Send` bound.
+pub struct LocalTaskObj {
+    ptr: *mut (),
+    poll_fn: unsafe fn(*mut (), &mut Context) -> Poll<()>,
+    drop_fn: unsafe fn(*mut ()),
+}
+
+impl LocalTaskObj {
+    /// Create a `LocalTaskObj` from a custom trait object representation.
+    #[inline]
+    pub fn new<T: UnsafeTask>(t: T) -> LocalTaskObj {
+        LocalTaskObj {
+            ptr: t.into_raw(),
+            poll_fn: T::poll,
+            drop_fn: T::drop,
+        }
+    }
+
+    /// Converts the `LocalTaskObj` into a `TaskObj`
+    /// To make this operation safe one has to ensure that the `UnsafeTask`
+    /// 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)
+    }
+}
+
+impl fmt::Debug for LocalTaskObj {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("LocalTaskObj")
+            .finish()
+    }
+}
+
+impl From<TaskObj> for LocalTaskObj {
+    fn from(task: TaskObj) -> LocalTaskObj {
+        unsafe {
+            // Safety: Both structs have the same memory layout
+            mem::transmute::<TaskObj, LocalTaskObj>(task)
+        }
+    }
+}
+
+impl Future for LocalTaskObj {
+    type Output = ();
+
+    #[inline]
+    fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
+        unsafe {
+            (self.poll_fn)(self.ptr, cx)
+        }
+    }
+}
+
+impl Drop for LocalTaskObj {
+    fn drop(&mut self) {
+        unsafe {
+            (self.drop_fn)(self.ptr)
+        }
+    }
+}
+
 /// A custom implementation of a task trait object for `TaskObj`, providing
 /// a hand-rolled vtable.
 ///
@@ -74,7 +139,7 @@ impl Drop for TaskObj {
 /// The implementor must guarantee that it is safe to call `poll` repeatedly (in
 /// a non-concurrent fashion) with the result of `into_raw` until `drop` is
 /// called.
-pub unsafe trait UnsafeTask: Send + 'static {
+pub unsafe trait UnsafeTask: 'static {
     /// Convert a owned instance into a (conceptually owned) void pointer.
     fn into_raw(self) -> *mut ();