]> git.lizzy.rs Git - rust.git/blob - src/libcore/task/task.rs
Rollup merge of #51765 - jonas-schievink:patch-1, r=KodrAus
[rust.git] / src / libcore / task / task.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![unstable(feature = "futures_api",
12             reason = "futures in libcore are unstable",
13             issue = "50547")]
14
15 use fmt;
16 use future::Future;
17 use mem::PinMut;
18 use super::{Context, Poll};
19
20 /// A custom trait object for polling tasks, roughly akin to
21 /// `Box<Future<Output = ()>>`.
22 /// Contrary to `TaskObj`, `LocalTaskObj` does not have a `Send` bound.
23 pub struct LocalTaskObj {
24     ptr: *mut (),
25     poll_fn: unsafe fn(*mut (), &mut Context) -> Poll<()>,
26     drop_fn: unsafe fn(*mut ()),
27 }
28
29 impl LocalTaskObj {
30     /// Create a `LocalTaskObj` from a custom trait object representation.
31     #[inline]
32     pub fn new<T: UnsafeTask>(t: T) -> LocalTaskObj {
33         LocalTaskObj {
34             ptr: t.into_raw(),
35             poll_fn: T::poll,
36             drop_fn: T::drop,
37         }
38     }
39
40     /// Converts the `LocalTaskObj` into a `TaskObj`
41     /// To make this operation safe one has to ensure that the `UnsafeTask`
42     /// instance from which this `LocalTaskObj` was created actually implements
43     /// `Send`.
44     pub unsafe fn as_task_obj(self) -> TaskObj {
45         TaskObj(self)
46     }
47 }
48
49 impl fmt::Debug for LocalTaskObj {
50     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51         f.debug_struct("LocalTaskObj")
52             .finish()
53     }
54 }
55
56 impl From<TaskObj> for LocalTaskObj {
57     fn from(task: TaskObj) -> LocalTaskObj {
58         task.0
59     }
60 }
61
62 impl Future for LocalTaskObj {
63     type Output = ();
64
65     #[inline]
66     fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
67         unsafe {
68             (self.poll_fn)(self.ptr, cx)
69         }
70     }
71 }
72
73 impl Drop for LocalTaskObj {
74     fn drop(&mut self) {
75         unsafe {
76             (self.drop_fn)(self.ptr)
77         }
78     }
79 }
80
81 /// A custom trait object for polling tasks, roughly akin to
82 /// `Box<Future<Output = ()> + Send>`.
83 pub struct TaskObj(LocalTaskObj);
84
85 unsafe impl Send for TaskObj {}
86
87 impl TaskObj {
88     /// Create a `TaskObj` from a custom trait object representation.
89     #[inline]
90     pub fn new<T: UnsafeTask + Send>(t: T) -> TaskObj {
91         TaskObj(LocalTaskObj::new(t))
92     }
93 }
94
95 impl fmt::Debug for TaskObj {
96     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97         f.debug_struct("TaskObj")
98             .finish()
99     }
100 }
101
102 impl Future for TaskObj {
103     type Output = ();
104
105     #[inline]
106     fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
107         let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
108         pinned_field.poll(cx)
109     }
110 }
111
112 /// A custom implementation of a task trait object for `TaskObj`, providing
113 /// a hand-rolled vtable.
114 ///
115 /// This custom representation is typically used only in `no_std` contexts,
116 /// where the default `Box`-based implementation is not available.
117 ///
118 /// The implementor must guarantee that it is safe to call `poll` repeatedly (in
119 /// a non-concurrent fashion) with the result of `into_raw` until `drop` is
120 /// called.
121 pub unsafe trait UnsafeTask: 'static {
122     /// Convert a owned instance into a (conceptually owned) void pointer.
123     fn into_raw(self) -> *mut ();
124
125     /// Poll the task represented by the given void pointer.
126     ///
127     /// # Safety
128     ///
129     /// The trait implementor must guarantee that it is safe to repeatedly call
130     /// `poll` with the result of `into_raw` until `drop` is called; such calls
131     /// are not, however, allowed to race with each other or with calls to `drop`.
132     unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll<()>;
133
134     /// Drops the task represented by the given void pointer.
135     ///
136     /// # Safety
137     ///
138     /// The trait implementor must guarantee that it is safe to call this
139     /// function once per `into_raw` invocation; that call cannot race with
140     /// other calls to `drop` or `poll`.
141     unsafe fn drop(task: *mut ());
142 }