1 //! Types and Traits for working with asynchronous tasks.
5 #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
8 #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
11 use core::marker::PhantomData;
13 use core::ptr::{self, NonNull};
16 /// A way of waking up a specific task.
18 /// Any task executor must provide a way of signaling that a task it owns
19 /// is ready to be `poll`ed again. Executors do so by implementing this trait.
20 pub trait Wake: Send + Sync {
21 /// Indicates that the associated task is ready to make progress and should
24 /// Executors generally maintain a queue of "ready" tasks; `wake` should place
25 /// the associated task onto this queue.
26 fn wake(arc_self: &Arc<Self>);
28 /// Indicates that the associated task is ready to make progress and should
29 /// be `poll`ed. This function is like `wake`, but can only be called from the
30 /// thread on which this `Wake` was created.
32 /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
33 /// the associated task onto this queue.
35 unsafe fn wake_local(arc_self: &Arc<Self>) {
40 #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
41 struct ArcWrapped<T>(PhantomData<T>);
43 unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
45 unsafe fn clone_raw(&self) -> Waker {
46 let me: *const ArcWrapped<T> = self;
47 let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
52 unsafe fn drop_raw(&self) {
53 let mut me: *const ArcWrapped<T> = self;
54 let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
55 ptr::drop_in_place(me);
59 unsafe fn wake(&self) {
60 let me: *const ArcWrapped<T> = self;
61 T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
65 unsafe fn wake_local(&self) {
66 let me: *const ArcWrapped<T> = self;
67 T::wake_local(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
71 impl<T> From<Arc<T>> for Waker
72 where T: Wake + 'static,
74 fn from(rc: Arc<T>) -> Self {
76 let ptr = mem::transmute::<Arc<T>, NonNull<ArcWrapped<T>>>(rc);
82 /// Creates a `LocalWaker` from a local `wake`.
84 /// This function requires that `wake` is "local" (created on the current thread).
85 /// The resulting `LocalWaker` will call `wake.wake_local()` when awoken, and
86 /// will call `wake.wake()` if awoken after being converted to a `Waker`.
88 pub unsafe fn local_waker<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
89 let ptr = mem::transmute::<Arc<W>, NonNull<ArcWrapped<W>>>(wake);
93 struct NonLocalAsLocal<T>(ArcWrapped<T>);
95 unsafe impl<T: Wake + 'static> UnsafeWake for NonLocalAsLocal<T> {
97 unsafe fn clone_raw(&self) -> Waker {
102 unsafe fn drop_raw(&self) {
107 unsafe fn wake(&self) {
112 unsafe fn wake_local(&self) {
113 // Since we're nonlocal, we can't call wake_local
118 /// Creates a `LocalWaker` from a non-local `wake`.
120 /// This function is similar to `local_waker`, but does not require that `wake`
121 /// is local to the current thread. The resulting `LocalWaker` will call
122 /// `wake.wake()` when awoken.
124 pub fn local_waker_from_nonlocal<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
126 let ptr = mem::transmute::<Arc<W>, NonNull<NonLocalAsLocal<W>>>(wake);