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::*;
15 #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
16 pub use self::if_arc::*;
18 #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
21 use core::marker::PhantomData;
23 use core::ptr::{self, NonNull};
26 /// A way of waking up a specific task.
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
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>);
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.
42 /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
43 /// the associated task onto this queue.
45 unsafe fn wake_local(arc_self: &Arc<Self>) {
50 #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
51 struct ArcWrapped<T>(PhantomData<T>);
53 unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
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();
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);
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>))
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>))
81 impl<T> From<Arc<T>> for Waker
82 where T: Wake + 'static,
84 fn from(rc: Arc<T>) -> Self {
86 let ptr = mem::transmute::<Arc<T>, NonNull<ArcWrapped<T>>>(rc);
92 /// Creates a `LocalWaker` from a local `wake`.
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`.
98 pub unsafe fn local_waker<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
99 let ptr = mem::transmute::<Arc<W>, NonNull<ArcWrapped<W>>>(wake);
103 struct NonLocalAsLocal<T>(ArcWrapped<T>);
105 unsafe impl<T: Wake + 'static> UnsafeWake for NonLocalAsLocal<T> {
107 unsafe fn clone_raw(&self) -> Waker {
112 unsafe fn drop_raw(&self) {
117 unsafe fn wake(&self) {
122 unsafe fn wake_local(&self) {
123 // Since we're nonlocal, we can't call wake_local
128 /// Creates a `LocalWaker` from a non-local `wake`.
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.
134 pub fn local_waker_from_nonlocal<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
136 let ptr = mem::transmute::<Arc<W>, NonNull<NonLocalAsLocal<W>>>(wake);