From b58cd6973654126caa3db942208ef3a82e93f324 Mon Sep 17 00:00:00 2001 From: Moritz Gunz Date: Mon, 14 Dec 2020 16:53:30 +0100 Subject: [PATCH 1/6] Expose nameable future for TaskLocal::scope --- tokio/src/task/mod.rs | 2 +- tokio/src/task/task_local.rs | 37 +++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/tokio/src/task/mod.rs b/tokio/src/task/mod.rs index 5dc5e72c01e..04427889d3b 100644 --- a/tokio/src/task/mod.rs +++ b/tokio/src/task/mod.rs @@ -235,5 +235,5 @@ cfg_rt! { pub use local::{spawn_local, LocalSet}; mod task_local; - pub use task_local::LocalKey; + pub use task_local::{LocalKey, TaskLocalFuture}; } diff --git a/tokio/src/task/task_local.rs b/tokio/src/task/task_local.rs index bc2e54a4e18..468f9634041 100644 --- a/tokio/src/task/task_local.rs +++ b/tokio/src/task/task_local.rs @@ -115,7 +115,7 @@ impl LocalKey { /// }).await; /// # } /// ``` - pub async fn scope(&'static self, value: T, f: F) -> F::Output + pub fn scope(&'static self, value: T, f: F) -> TaskLocalFuture where F: Future, { @@ -124,7 +124,6 @@ impl LocalKey { slot: Some(value), future: f, } - .await } /// Accesses the current task-local and runs the provided closure. @@ -177,7 +176,28 @@ impl fmt::Debug for LocalKey { } pin_project! { - struct TaskLocalFuture { + /// A future that sets a value `T` of a task local for the future `F` during + /// its execution. + /// + /// The value of the task-local must be `'static` and will be dropped on the + /// completion of the future. + /// + /// Created by the function [`LocalKey::scope`](self::LocalKey::scope). + /// + /// ### Examples + /// + /// ``` + /// # async fn dox() { + /// tokio::task_local! { + /// static NUMBER: u32; + /// } + /// + /// NUMBER.scope(1, async move { + /// println!("task local value: {}", NUMBER.get()); + /// }).await; + /// # } + /// ``` + pub struct TaskLocalFuture { local: &'static LocalKey, slot: Option, #[pin] @@ -217,8 +237,15 @@ impl Future for TaskLocalFuture { } } -// Required to make `pin_project` happy. -trait StaticLifetime: 'static {} +mod sealed { + pub trait Sealed {} + + impl Sealed for T {} +} + +/// Required to make `pin_project` happy. +#[doc(hidden)] +pub trait StaticLifetime: self::sealed::Sealed + 'static {} impl StaticLifetime for T {} /// An error returned by [`LocalKey::try_with`](method@LocalKey::try_with). From 1fbc864115b5acd46d9144879e8a7ac4b436b146 Mon Sep 17 00:00:00 2001 From: Moritz Gunz Date: Tue, 15 Dec 2020 10:41:47 +0100 Subject: [PATCH 2/6] Export TaskLocalFuture under tokio::task::future --- tokio/src/task/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tokio/src/task/mod.rs b/tokio/src/task/mod.rs index 04427889d3b..33024819321 100644 --- a/tokio/src/task/mod.rs +++ b/tokio/src/task/mod.rs @@ -235,5 +235,10 @@ cfg_rt! { pub use local::{spawn_local, LocalSet}; mod task_local; - pub use task_local::{LocalKey, TaskLocalFuture}; + pub use task_local::LocalKey; + + /// Task-related futures. + pub mod future { + pub use super::task_local::TaskLocalFuture; + } } From 6c00e3c8bca3189c0d1fef259b8f146e981ffd27 Mon Sep 17 00:00:00 2001 From: Moritz Gunz Date: Tue, 15 Dec 2020 10:53:18 +0100 Subject: [PATCH 3/6] Replace pin_project_lite with hand-rolled implementation --- tokio/src/task/task_local.rs | 91 +++++++++++++++++------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/tokio/src/task/task_local.rs b/tokio/src/task/task_local.rs index 468f9634041..bd67e8fb2e1 100644 --- a/tokio/src/task/task_local.rs +++ b/tokio/src/task/task_local.rs @@ -1,4 +1,3 @@ -use pin_project_lite::pin_project; use std::cell::RefCell; use std::error::Error; use std::future::Future; @@ -175,34 +174,33 @@ impl fmt::Debug for LocalKey { } } -pin_project! { - /// A future that sets a value `T` of a task local for the future `F` during - /// its execution. - /// - /// The value of the task-local must be `'static` and will be dropped on the - /// completion of the future. - /// - /// Created by the function [`LocalKey::scope`](self::LocalKey::scope). - /// - /// ### Examples - /// - /// ``` - /// # async fn dox() { - /// tokio::task_local! { - /// static NUMBER: u32; - /// } - /// - /// NUMBER.scope(1, async move { - /// println!("task local value: {}", NUMBER.get()); - /// }).await; - /// # } - /// ``` - pub struct TaskLocalFuture { - local: &'static LocalKey, - slot: Option, - #[pin] - future: F, - } +/// A future that sets a value `T` of a task local for the future `F` during +/// its execution. +/// +/// The value of the task-local must be `'static` and will be dropped on the +/// completion of the future. +/// +/// Created by the function [`LocalKey::scope`](self::LocalKey::scope). +/// +/// ### Examples +/// +/// ``` +/// # async fn dox() { +/// tokio::task_local! { +/// static NUMBER: u32; +/// } +/// +/// NUMBER.scope(1, async move { +/// println!("task local value: {}", NUMBER.get()); +/// }).await; +/// # } +/// ``` +#[must_use = "futures do nothing unless polled"] +#[derive(Debug)] +pub struct TaskLocalFuture { + local: &'static LocalKey, + slot: Option, + future: F, } impl Future for TaskLocalFuture { @@ -222,31 +220,28 @@ impl Future for TaskLocalFuture { } } - let mut project = self.project(); - let val = project.slot.take(); + unsafe { + let TaskLocalFuture { + local, + slot, + future, + } = self.get_unchecked_mut(); - let prev = project.local.inner.with(|c| c.replace(val)); + let val = slot.take(); + let prev = local.inner.with(|c| c.replace(val)); - let _guard = Guard { - prev, - slot: &mut project.slot, - local: *project.local, - }; + let _guard = Guard { + prev, + slot, + local: &local, + }; - project.future.poll(cx) + Pin::new_unchecked(future).poll(cx) + } } } -mod sealed { - pub trait Sealed {} - - impl Sealed for T {} -} - -/// Required to make `pin_project` happy. -#[doc(hidden)] -pub trait StaticLifetime: self::sealed::Sealed + 'static {} -impl StaticLifetime for T {} +impl Unpin for TaskLocalFuture {} /// An error returned by [`LocalKey::try_with`](method@LocalKey::try_with). #[derive(Clone, Copy, Eq, PartialEq)] From d92aa3823683bfc95516d29015f6a68f8c5fc0bc Mon Sep 17 00:00:00 2001 From: Moritz Gunz Date: Tue, 15 Dec 2020 11:31:01 +0100 Subject: [PATCH 4/6] Revert "Replace pin_project_lite with hand-rolled implementation" This reverts commit 6c00e3c8bca3189c0d1fef259b8f146e981ffd27. --- tokio/src/task/task_local.rs | 91 +++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/tokio/src/task/task_local.rs b/tokio/src/task/task_local.rs index bd67e8fb2e1..468f9634041 100644 --- a/tokio/src/task/task_local.rs +++ b/tokio/src/task/task_local.rs @@ -1,3 +1,4 @@ +use pin_project_lite::pin_project; use std::cell::RefCell; use std::error::Error; use std::future::Future; @@ -174,33 +175,34 @@ impl fmt::Debug for LocalKey { } } -/// A future that sets a value `T` of a task local for the future `F` during -/// its execution. -/// -/// The value of the task-local must be `'static` and will be dropped on the -/// completion of the future. -/// -/// Created by the function [`LocalKey::scope`](self::LocalKey::scope). -/// -/// ### Examples -/// -/// ``` -/// # async fn dox() { -/// tokio::task_local! { -/// static NUMBER: u32; -/// } -/// -/// NUMBER.scope(1, async move { -/// println!("task local value: {}", NUMBER.get()); -/// }).await; -/// # } -/// ``` -#[must_use = "futures do nothing unless polled"] -#[derive(Debug)] -pub struct TaskLocalFuture { - local: &'static LocalKey, - slot: Option, - future: F, +pin_project! { + /// A future that sets a value `T` of a task local for the future `F` during + /// its execution. + /// + /// The value of the task-local must be `'static` and will be dropped on the + /// completion of the future. + /// + /// Created by the function [`LocalKey::scope`](self::LocalKey::scope). + /// + /// ### Examples + /// + /// ``` + /// # async fn dox() { + /// tokio::task_local! { + /// static NUMBER: u32; + /// } + /// + /// NUMBER.scope(1, async move { + /// println!("task local value: {}", NUMBER.get()); + /// }).await; + /// # } + /// ``` + pub struct TaskLocalFuture { + local: &'static LocalKey, + slot: Option, + #[pin] + future: F, + } } impl Future for TaskLocalFuture { @@ -220,28 +222,31 @@ impl Future for TaskLocalFuture { } } - unsafe { - let TaskLocalFuture { - local, - slot, - future, - } = self.get_unchecked_mut(); + let mut project = self.project(); + let val = project.slot.take(); - let val = slot.take(); - let prev = local.inner.with(|c| c.replace(val)); + let prev = project.local.inner.with(|c| c.replace(val)); - let _guard = Guard { - prev, - slot, - local: &local, - }; + let _guard = Guard { + prev, + slot: &mut project.slot, + local: *project.local, + }; - Pin::new_unchecked(future).poll(cx) - } + project.future.poll(cx) } } -impl Unpin for TaskLocalFuture {} +mod sealed { + pub trait Sealed {} + + impl Sealed for T {} +} + +/// Required to make `pin_project` happy. +#[doc(hidden)] +pub trait StaticLifetime: self::sealed::Sealed + 'static {} +impl StaticLifetime for T {} /// An error returned by [`LocalKey::try_with`](method@LocalKey::try_with). #[derive(Clone, Copy, Eq, PartialEq)] From 2a62b9bbdec7cfd53578f2cd7a48413554c5b8e5 Mon Sep 17 00:00:00 2001 From: Moritz Gunz Date: Tue, 15 Dec 2020 11:32:48 +0100 Subject: [PATCH 5/6] Replace StaticLifetime shenanigans with properly formatted generic bounds --- tokio/src/task/task_local.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tokio/src/task/task_local.rs b/tokio/src/task/task_local.rs index 468f9634041..704403a18b9 100644 --- a/tokio/src/task/task_local.rs +++ b/tokio/src/task/task_local.rs @@ -197,7 +197,10 @@ pin_project! { /// }).await; /// # } /// ``` - pub struct TaskLocalFuture { + pub struct TaskLocalFuture + where + T: 'static + { local: &'static LocalKey, slot: Option, #[pin] @@ -237,17 +240,6 @@ impl Future for TaskLocalFuture { } } -mod sealed { - pub trait Sealed {} - - impl Sealed for T {} -} - -/// Required to make `pin_project` happy. -#[doc(hidden)] -pub trait StaticLifetime: self::sealed::Sealed + 'static {} -impl StaticLifetime for T {} - /// An error returned by [`LocalKey::try_with`](method@LocalKey::try_with). #[derive(Clone, Copy, Eq, PartialEq)] pub struct AccessError { From 818cb97c546dab2096559467964185c890285834 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 6 Jul 2021 17:00:35 +0200 Subject: [PATCH 6/6] Update tokio/src/task/mod.rs --- tokio/src/task/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokio/src/task/mod.rs b/tokio/src/task/mod.rs index f2e2a4c2eaa..ea9878736db 100644 --- a/tokio/src/task/mod.rs +++ b/tokio/src/task/mod.rs @@ -306,7 +306,7 @@ cfg_rt! { } /// Task-related futures. - pub mod future { + pub mod futures { pub use super::task_local::TaskLocalFuture; } }