]> git.lizzy.rs Git - rust.git/blob - src/liballoc/task.rs
Separate codepaths for fat and thin LTO in write.rs
[rust.git] / src / liballoc / 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 //! Types and Traits for working with asynchronous tasks.
12
13 pub use core::task::*;
14
15 #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
16 pub use self::if_arc::*;
17
18 #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
19 mod if_arc {
20     use super::*;
21     use core::marker::PhantomData;
22     use core::mem;
23     use core::ptr::{self, NonNull};
24     use sync::Arc;
25
26     /// A way of waking up a specific task.
27     ///
28     /// Any task executor must provide a way of signaling that a task it owns
29     /// is ready to be `poll`ed again. Executors do so by implementing this trait.
30     pub trait Wake: Send + Sync {
31         /// Indicates that the associated task is ready to make progress and should
32         /// be `poll`ed.
33         ///
34         /// Executors generally maintain a queue of "ready" tasks; `wake` should place
35         /// the associated task onto this queue.
36         fn wake(arc_self: &Arc<Self>);
37
38         /// Indicates that the associated task is ready to make progress and should
39         /// be `poll`ed. This function is like `wake`, but can only be called from the
40         /// thread on which this `Wake` was created.
41         ///
42         /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
43         /// the associated task onto this queue.
44         #[inline]
45         unsafe fn wake_local(arc_self: &Arc<Self>) {
46             Self::wake(arc_self);
47         }
48     }
49
50     #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
51     struct ArcWrapped<T>(PhantomData<T>);
52
53     unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
54         #[inline]
55         unsafe fn clone_raw(&self) -> Waker {
56             let me: *const ArcWrapped<T> = self;
57             let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
58             Waker::from(arc)
59         }
60
61         #[inline]
62         unsafe fn drop_raw(&self) {
63             let mut me: *const ArcWrapped<T> = self;
64             let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
65             ptr::drop_in_place(me);
66         }
67
68         #[inline]
69         unsafe fn wake(&self) {
70             let me: *const ArcWrapped<T> = self;
71             T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
72         }
73
74         #[inline]
75         unsafe fn wake_local(&self) {
76             let me: *const ArcWrapped<T> = self;
77             T::wake_local(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
78         }
79     }
80
81     impl<T> From<Arc<T>> for Waker
82         where T: Wake + 'static,
83     {
84         fn from(rc: Arc<T>) -> Self {
85             unsafe {
86                 let ptr = mem::transmute::<Arc<T>, NonNull<ArcWrapped<T>>>(rc);
87                 Waker::new(ptr)
88             }
89         }
90     }
91
92     /// Creates a `LocalWaker` from a local `wake`.
93     ///
94     /// This function requires that `wake` is "local" (created on the current thread).
95     /// The resulting `LocalWaker` will call `wake.wake_local()` when awoken, and
96     /// will call `wake.wake()` if awoken after being converted to a `Waker`.
97     #[inline]
98     pub unsafe fn local_waker<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
99         let ptr = mem::transmute::<Arc<W>, NonNull<ArcWrapped<W>>>(wake);
100         LocalWaker::new(ptr)
101     }
102
103     struct NonLocalAsLocal<T>(ArcWrapped<T>);
104
105     unsafe impl<T: Wake + 'static> UnsafeWake for NonLocalAsLocal<T> {
106         #[inline]
107         unsafe fn clone_raw(&self) -> Waker {
108             self.0.clone_raw()
109         }
110
111         #[inline]
112         unsafe fn drop_raw(&self) {
113             self.0.drop_raw()
114         }
115
116         #[inline]
117         unsafe fn wake(&self) {
118             self.0.wake()
119         }
120
121         #[inline]
122         unsafe fn wake_local(&self) {
123             // Since we're nonlocal, we can't call wake_local
124             self.0.wake()
125         }
126     }
127
128     /// Creates a `LocalWaker` from a non-local `wake`.
129     ///
130     /// This function is similar to `local_waker`, but does not require that `wake`
131     /// is local to the current thread. The resulting `LocalWaker` will call
132     /// `wake.wake()` when awoken.
133     #[inline]
134     pub fn local_waker_from_nonlocal<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
135         unsafe {
136             let ptr = mem::transmute::<Arc<W>, NonNull<NonLocalAsLocal<W>>>(wake);
137             LocalWaker::new(ptr)
138         }
139     }
140 }