summaryrefslogtreecommitdiff
path: root/library/alloc/src/task.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-27 17:39:01 +0000
committerbors <bors@rust-lang.org>2020-07-27 17:39:01 +0000
commit54e000891ffccd4cbfb92146b92736c83085df63 (patch)
tree1200bb13eb9ae22def4c43bc657bc56da8faedc6 /library/alloc/src/task.rs
parent4a90e36c85336d1d4b209556c1a9733210bbff19 (diff)
parent6d9705220fec4553d693a7c19d99496e14c89edf (diff)
downloadrust-tmp-nightly.tar.gz
Auto merge of #73265 - mark-i-m:mv-std, r=<try>tmp-nightly
mv std libs to library/ This is the first step in refactoring the directory layout of this repository, with further followup steps planned (but not done yet). Background: currently, all crates are under src/, without nested src directories and with the unconventional `lib*` prefixes (e.g., `src/libcore/lib.rs`). This directory structures is not idiomatic and makes the `src/` directory rather overwhelming. To improve contributor experience and make things a bit more approachable, we are reorganizing the repo a bit. In this PR, we move the standard libs (basically anything that is "runtime", as opposed to part of the compiler, build system, or one of the tools, etc). The new layout moves these libraries to a new `library/` directory in the root of the repo. Additionally, we remove the `lib*` prefixes and add nested `src/` directories. The other crates/tools in this repo are not touched. So in summary: ``` library/<crate>/src/*.rs src/<all the rest> // unchanged ``` where `<crate>` is: - core - alloc - std - test - proc_macro - panic_abort - panic_unwind - profiler_builtins - term - unwind - rtstartup - backtrace - rustc-std-workspace-* There was a lot of discussion about this and a few rounds of compiler team approvals, FCPs, MCPs, and nominations. The original MCP is https://github.com/rust-lang/compiler-team/issues/298. The final approval of the compiler team was given here: https://github.com/rust-lang/rust/pull/73265#issuecomment-659498446. The name `library` was chosen to complement a later move of the compiler crates to a `compiler/` directory. There was a lot of discussion around adding the nested `src/` directories. Note that this does increase the nesting depth (plausibly important for manual traversal of the tree, e.g., through GitHub's UI or `cd`), but this is deemed to be better as it fits the standard layout of Rust crates throughout most of the ecosystem, though there is some debate about how much this should apply to multi-crate projects. Overall, there seem to be more people in favor of nested `src/` than against. After this PR, there are no dependencies out of the `library/` directory except on the `build_helper` (or crates.io crates).
Diffstat (limited to 'library/alloc/src/task.rs')
-rw-r--r--library/alloc/src/task.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs
new file mode 100644
index 00000000000..252e04a4105
--- /dev/null
+++ b/library/alloc/src/task.rs
@@ -0,0 +1,91 @@
+#![unstable(feature = "wake_trait", issue = "69912")]
+//! Types and Traits for working with asynchronous tasks.
+use core::mem::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.
+///
+/// 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`][arc]. Some executors (especially
+/// those for embedded systems) cannot use this API, which is why [`RawWaker`]
+/// exists as an alternative for those systems.
+///
+/// [arc]: ../../std/sync/struct.Arc.html
+#[unstable(feature = "wake_trait", issue = "69912")]
+pub trait Wake {
+ /// Wake this task.
+ #[unstable(feature = "wake_trait", issue = "69912")]
+ fn wake(self: Arc<Self>);
+
+ /// Wake this task without consuming the waker.
+ ///
+ /// If an executor supports a cheaper way to wake without consuming the
+ /// waker, it should override this method. By default, it clones the
+ /// [`Arc`] and calls `wake` on the clone.
+ #[unstable(feature = "wake_trait", issue = "69912")]
+ fn wake_by_ref(self: &Arc<Self>) {
+ self.clone().wake();
+ }
+}
+
+#[unstable(feature = "wake_trait", issue = "69912")]
+impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for Waker {
+ fn from(waker: Arc<W>) -> Waker {
+ // SAFETY: This is safe because raw_waker safely constructs
+ // a RawWaker from Arc<W>.
+ unsafe { Waker::from_raw(raw_waker(waker)) }
+ }
+}
+
+#[unstable(feature = "wake_trait", issue = "69912")]
+impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
+ fn from(waker: Arc<W>) -> RawWaker {
+ raw_waker(waker)
+ }
+}
+
+// NB: This private function for constructing a RawWaker is used, rather than
+// inlining this into the `From<Arc<W>> for RawWaker` impl, to ensure that
+// the safety of `From<Arc<W>> for Waker` does not depend on the correct
+// trait dispatch - instead both impls call this function directly and
+// 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 {
+ unsafe { Arc::incr_strong_count(waker as *const W) };
+ RawWaker::new(
+ waker as *const (),
+ &RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
+ )
+ }
+
+ // Wake by value, moving the Arc into the Wake::wake function
+ unsafe fn wake<W: Wake + Send + Sync + 'static>(waker: *const ()) {
+ let waker = unsafe { Arc::from_raw(waker as *const W) };
+ <W as Wake>::wake(waker);
+ }
+
+ // 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 = unsafe { ManuallyDrop::new(Arc::from_raw(waker as *const W)) };
+ <W as Wake>::wake_by_ref(&waker);
+ }
+
+ // Decrement the reference count of the Arc on drop
+ unsafe fn drop_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) {
+ unsafe { Arc::decr_strong_count(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>),
+ )
+}