Skip to content

Commit

Permalink
task: add sync_scope for LocalKey (#3612)
Browse files Browse the repository at this point in the history
  • Loading branch information
quininer authored Mar 22, 2021
1 parent 8ed825f commit c659e4a
Showing 1 changed file with 40 additions and 5 deletions.
45 changes: 40 additions & 5 deletions tokio/src/task/task_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,35 @@ impl<T: 'static> LocalKey<T> {
.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<F, R>(&'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
Expand Down Expand Up @@ -185,10 +214,8 @@ pin_project! {
}
}

impl<T: 'static, F: Future> Future for TaskLocalFuture<T, F> {
type Output = F::Output;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
impl<T: 'static, F> TaskLocalFuture<T, F> {
fn with_task<F2: FnOnce(Pin<&mut F>) -> R, R>(self: Pin<&mut Self>, f: F2) -> R {
struct Guard<'a, T: 'static> {
local: &'static LocalKey<T>,
slot: &'a mut Option<T>,
Expand All @@ -213,7 +240,15 @@ impl<T: 'static, F: Future> Future for TaskLocalFuture<T, F> {
local: *project.local,
};

project.future.poll(cx)
f(project.future)
}
}

impl<T: 'static, F: Future> Future for TaskLocalFuture<T, F> {
type Output = F::Output;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.with_task(|f| f.poll(cx))
}
}

Expand Down

0 comments on commit c659e4a

Please sign in to comment.