diff options
| author | Josef Reinhard Brandl <mail@josefbrandl.de> | 2018-06-26 17:06:20 +0200 |
|---|---|---|
| committer | Josef Reinhard Brandl <mail@josefbrandl.de> | 2018-06-26 17:06:20 +0200 |
| commit | 433e6b31a75eea5ce45493acc63eae462d740338 (patch) | |
| tree | 74971086254a1d533d177ec8848050bed679230a /src/libcore/task | |
| parent | 1f9aa1332fc9f0194bac1761ef04e54564e26fc8 (diff) | |
| download | rust-433e6b31a75eea5ce45493acc63eae462d740338.tar.gz rust-433e6b31a75eea5ce45493acc63eae462d740338.zip | |
Add `LocalTaskObj`
Diffstat (limited to 'src/libcore/task')
| -rw-r--r-- | src/libcore/task/mod.rs | 4 | ||||
| -rw-r--r-- | src/libcore/task/spawn_error.rs | 33 | ||||
| -rw-r--r-- | src/libcore/task/task.rs | 71 |
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 (); |
