about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorWithout Boats <woboats@gmail.com>2020-01-31 17:01:41 +0100
committerWithout Boats <woboats@gmail.com>2020-03-23 15:45:30 +0100
commitc9acdb0bd4e7b1dc0a565926467b1b6365dbda14 (patch)
tree1411344d23a926fb7ec1f81481bea7ea72490f0e /src/liballoc
parentd8a835f1a13efab31c59fab615ce6926b3a047bf (diff)
downloadrust-c9acdb0bd4e7b1dc0a565926467b1b6365dbda14.tar.gz
rust-c9acdb0bd4e7b1dc0a565926467b1b6365dbda14.zip
Improve safety implementation, fix typos
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/task.rs28
1 files changed, 12 insertions, 16 deletions
diff --git a/src/liballoc/task.rs b/src/liballoc/task.rs
index 8e0466d9a2f..3fb148e8e34 100644
--- a/src/liballoc/task.rs
+++ b/src/liballoc/task.rs
@@ -1,12 +1,12 @@
 #![unstable(feature = "wake_trait", issue = "0")]
 //! Types and Traits for working with asynchronous tasks.
-use core::mem;
-use core::task::{Waker, RawWaker, RawWakerVTable};
+use core::mem::{self, ManuallyDrop};
+use core::task::{RawWaker, RawWakerVTable, Waker};
 
 use crate::sync::Arc;
 
 /// The implementation of waking a task on an executor.
-/// 
+///
 /// This trait can be used to create a [`Waker`]. An executor can define an
 /// implementation of this trait, and use that to construct a Waker to pass
 /// to the tasks that are executed on that executor.
@@ -14,7 +14,7 @@ use crate::sync::Arc;
 /// This trait is a memory-safe and ergonomic alternative to constructing a
 /// [`RawWaker`]. It supports the common executor design in which the data
 /// used to wake up a task is stored in an [`Arc`]. Some executors (especially
-/// those for embedded systems) cannot use this API, which is way [`RawWaker`]
+/// those for embedded systems) cannot use this API, which is why [`RawWaker`]
 /// exists as an alternative for those systems.
 #[unstable(feature = "wake_trait", issue = "0")]
 pub trait Wake {
@@ -36,9 +36,9 @@ pub trait Wake {
 #[unstable(feature = "wake_trait", issue = "0")]
 impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for Waker {
     fn from(waker: Arc<W>) -> Waker {
-        unsafe {
-            Waker::from_raw(raw_waker(waker))
-        }
+        // SAFETY: This is safe because raw_waker safely constructs
+        // a RawWaker from Arc<W>.
+        unsafe { Waker::from_raw(raw_waker(waker)) }
     }
 }
 
@@ -56,7 +56,6 @@ impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
 // explicitly.
 #[inline(always)]
 fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
-
     // Increment the reference count of the arc to clone it.
     unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
         let waker: Arc<W> = Arc::from_raw(waker as *const W);
@@ -70,11 +69,10 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
         Wake::wake(waker);
     }
 
-    // Wake by reference, forgetting the Arc to avoid decrementing the reference count
+    // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it
     unsafe fn wake_by_ref<W: Wake + Send + Sync + 'static>(waker: *const ()) {
-        let waker: Arc<W> = Arc::from_raw(waker as *const W);
+        let waker: ManuallyDrop<Arc<W>> = ManuallyDrop::new(Arc::from_raw(waker as *const W));
         Wake::wake_by_ref(&waker);
-        mem::forget(waker);
     }
 
     // Decrement the reference count of the Arc on drop
@@ -82,10 +80,8 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
         mem::drop(Arc::from_raw(waker as *const W));
     }
 
-    RawWaker::new(Arc::into_raw(waker) as *const (), &RawWakerVTable::new(
-        clone_waker::<W>,
-        wake::<W>,
-        wake_by_ref::<W>,
-        drop_waker::<W>,
+    RawWaker::new(
+        Arc::into_raw(waker) as *const (),
+        &RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
     ))
 }