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.
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.
11 //! Types and Traits for working with asynchronous tasks.
13 pub use core::task::*;
16 all(stage0, target_has_atomic = "ptr"),
17 all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
19 pub use self::if_arc::*;
22 all(stage0, target_has_atomic = "ptr"),
23 all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
27 use core::marker::PhantomData;
29 use core::ptr::{self, NonNull};
32 /// A way of waking up a specific task.
34 /// Any task executor must provide a way of signaling that a task it owns
35 /// is ready to be `poll`ed again. Executors do so by implementing this trait.
36 pub trait Wake: Send + Sync {
37 /// Indicates that the associated task is ready to make progress and should
40 /// Executors generally maintain a queue of "ready" tasks; `wake` should place
41 /// the associated task onto this queue.
42 fn wake(arc_self: &Arc<Self>);
44 /// Indicates that the associated task is ready to make progress and should
45 /// be `poll`ed. This function is like `wake`, but can only be called from the
46 /// thread on which this `Wake` was created.
48 /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
49 /// the associated task onto this queue.
51 unsafe fn wake_local(arc_self: &Arc<Self>) {
57 all(stage0, target_has_atomic = "ptr"),
58 all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
60 struct ArcWrapped<T>(PhantomData<T>);
62 unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
64 unsafe fn clone_raw(&self) -> Waker {
65 let me: *const ArcWrapped<T> = self;
66 let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
71 unsafe fn drop_raw(&self) {
72 let mut me: *const ArcWrapped<T> = self;
73 let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
74 ptr::drop_in_place(me);
78 unsafe fn wake(&self) {
79 let me: *const ArcWrapped<T> = self;
80 T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
84 unsafe fn wake_local(&self) {
85 let me: *const ArcWrapped<T> = self;
86 T::wake_local(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
90 impl<T> From<Arc<T>> for Waker
91 where T: Wake + 'static,
93 fn from(rc: Arc<T>) -> Self {
95 let ptr = mem::transmute::<Arc<T>, NonNull<ArcWrapped<T>>>(rc);
101 /// Creates a `LocalWaker` from a local `wake`.
103 /// This function requires that `wake` is "local" (created on the current thread).
104 /// The resulting `LocalWaker` will call `wake.wake_local()` when awoken, and
105 /// will call `wake.wake()` if awoken after being converted to a `Waker`.
107 pub unsafe fn local_waker<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
108 let ptr = mem::transmute::<Arc<W>, NonNull<ArcWrapped<W>>>(wake);
112 struct NonLocalAsLocal<T>(ArcWrapped<T>);
114 unsafe impl<T: Wake + 'static> UnsafeWake for NonLocalAsLocal<T> {
116 unsafe fn clone_raw(&self) -> Waker {
121 unsafe fn drop_raw(&self) {
126 unsafe fn wake(&self) {
131 unsafe fn wake_local(&self) {
132 // Since we're nonlocal, we can't call wake_local
137 /// Creates a `LocalWaker` from a non-local `wake`.
139 /// This function is similar to `local_waker`, but does not require that `wake`
140 /// is local to the current thread. The resulting `LocalWaker` will call
141 /// `wake.wake()` when awoken.
143 pub fn local_waker_from_nonlocal<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
145 let ptr = mem::transmute::<Arc<W>, NonNull<NonLocalAsLocal<W>>>(wake);