From c659e4a757b5a2a63378ead33917f4e072dba5dc Mon Sep 17 00:00:00 2001 From: quininer Date: Tue, 23 Mar 2021 00:02:10 +0800 Subject: [PATCH] task: add sync_scope for LocalKey (#3612) --- tokio/src/task/task_local.rs | 45 ++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/tokio/src/task/task_local.rs b/tokio/src/task/task_local.rs index bc2e54a4e..e240cb6e5 100644 --- a/tokio/src/task/task_local.rs +++ b/tokio/src/task/task_local.rs @@ -127,6 +127,35 @@ impl LocalKey { .await } + /// Sets a value `T` as the task-local value for the closure `F`. + /// + /// On completion of `scope`, the task-local will be dropped. + /// + /// ### Examples + /// + /// ``` + /// # async fn dox() { + /// tokio::task_local! { + /// static NUMBER: u32; + /// } + /// + /// NUMBER.sync_scope(1, || { + /// println!("task local value: {}", NUMBER.get()); + /// }); + /// # } + /// ``` + pub fn sync_scope(&'static self, value: T, f: F) -> R + where + F: FnOnce() -> R, + { + let mut scope = TaskLocalFuture { + local: &self, + slot: Some(value), + future: (), + }; + Pin::new(&mut scope).with_task(|_| f()) + } + /// Accesses the current task-local and runs the provided closure. /// /// # Panics @@ -185,10 +214,8 @@ pin_project! { } } -impl Future for TaskLocalFuture { - type Output = F::Output; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { +impl TaskLocalFuture { + fn with_task) -> R, R>(self: Pin<&mut Self>, f: F2) -> R { struct Guard<'a, T: 'static> { local: &'static LocalKey, slot: &'a mut Option, @@ -213,7 +240,15 @@ impl Future for TaskLocalFuture { local: *project.local, }; - project.future.poll(cx) + f(project.future) + } +} + +impl Future for TaskLocalFuture { + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.with_task(|f| f.poll(cx)) } }