about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJustin Karneges <justin@karneges.com>2024-03-28 09:55:07 -0700
committerJustin Karneges <justin@karneges.com>2024-03-29 10:12:10 -0700
commitc6ac3b02dbd74a4116f7198c442f419fee3cacc5 (patch)
tree8bf4b00bb129e0f14f907f7dcba31cc4aeb36bf6
parent10a7aa14fed9b528b74b0f098c4899c37c09a9c7 (diff)
downloadrust-c6ac3b02dbd74a4116f7198c442f419fee3cacc5.tar.gz
rust-c6ac3b02dbd74a4116f7198c442f419fee3cacc5.zip
Add `Context::ext`
-rw-r--r--library/core/src/task/wake.rs55
1 files changed, 52 insertions, 3 deletions
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 1b43c46bda5..227276aa349 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -2,6 +2,7 @@
 
 use crate::mem::transmute;
 
+use crate::any::Any;
 use crate::fmt;
 use crate::marker::PhantomData;
 use crate::ptr;
@@ -220,6 +221,12 @@ impl RawWakerVTable {
     }
 }
 
+#[derive(Debug)]
+enum ExtData<'a> {
+    Some(&'a mut dyn Any),
+    None(()),
+}
+
 /// The context of an asynchronous task.
 ///
 /// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
@@ -229,6 +236,7 @@ impl RawWakerVTable {
 pub struct Context<'a> {
     waker: &'a Waker,
     local_waker: &'a LocalWaker,
+    ext: ExtData<'a>,
     // Ensure we future-proof against variance changes by forcing
     // the lifetime to be invariant (argument-position lifetimes
     // are contravariant while return-position lifetimes are
@@ -257,6 +265,7 @@ impl<'a> Context<'a> {
     pub const fn waker(&self) -> &'a Waker {
         &self.waker
     }
+
     /// Returns a reference to the [`LocalWaker`] for the current task.
     #[inline]
     #[unstable(feature = "local_waker", issue = "118959")]
@@ -264,6 +273,17 @@ impl<'a> Context<'a> {
     pub const fn local_waker(&self) -> &'a LocalWaker {
         &self.local_waker
     }
+
+    /// Returns a reference to the extension data for the current task.
+    #[inline]
+    #[unstable(feature = "context_ext", issue = "none")]
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+    pub const fn ext(&mut self) -> &mut dyn Any {
+        match &mut self.ext {
+            ExtData::Some(data) => *data,
+            ExtData::None(unit) => unit,
+        }
+    }
 }
 
 #[stable(feature = "futures_api", since = "1.36.0")]
@@ -300,6 +320,7 @@ impl fmt::Debug for Context<'_> {
 pub struct ContextBuilder<'a> {
     waker: &'a Waker,
     local_waker: &'a LocalWaker,
+    ext: ExtData<'a>,
     // Ensure we future-proof against variance changes by forcing
     // the lifetime to be invariant (argument-position lifetimes
     // are contravariant while return-position lifetimes are
@@ -318,7 +339,27 @@ impl<'a> ContextBuilder<'a> {
     pub const fn from_waker(waker: &'a Waker) -> Self {
         // SAFETY: LocalWaker is just Waker without thread safety
         let local_waker = unsafe { transmute(waker) };
-        Self { waker: waker, local_waker, _marker: PhantomData, _marker2: PhantomData }
+        Self { waker: waker, local_waker, ext: ExtData::None(()), _marker: PhantomData, _marker2: PhantomData }
+    }
+
+    /// Create a ContextBuilder from an existing Context.
+    #[inline]
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+    #[unstable(feature = "context_ext", issue = "none")]
+    pub const fn from(cx: &'a mut Context<'_>) -> Self {
+        let ext = match &mut cx.ext {
+            ExtData::Some(ext) => ExtData::Some(*ext),
+            ExtData::None(()) => ExtData::None(()),
+        };
+        Self { waker: cx.waker, local_waker: cx.local_waker, ext, _marker: PhantomData, _marker2: PhantomData }
+    }
+
+    /// This method is used to set the value for the waker on `Context`.
+    #[inline]
+    #[unstable(feature = "context_ext", issue = "none")]
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+    pub const fn waker(self, waker: &'a Waker) -> Self {
+        Self { waker, ..self }
     }
 
     /// This method is used to set the value for the local waker on `Context`.
@@ -329,13 +370,21 @@ impl<'a> ContextBuilder<'a> {
         Self { local_waker, ..self }
     }
 
+    /// This method is used to set the value for the extension data on `Context`.
+    #[inline]
+    #[unstable(feature = "context_ext", issue = "none")]
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+    pub const fn ext(self, data: &'a mut dyn Any) -> Self {
+        Self { ext: ExtData::Some(data), ..self }
+    }
+
     /// Builds the `Context`.
     #[inline]
     #[unstable(feature = "local_waker", issue = "118959")]
     #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     pub const fn build(self) -> Context<'a> {
-        let ContextBuilder { waker, local_waker, _marker, _marker2 } = self;
-        Context { waker, local_waker, _marker, _marker2 }
+        let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self;
+        Context { waker, local_waker, ext, _marker, _marker2 }
     }
 }