Repository: tokio-rs/tokio
File: tokio/src/task/local.rs (Rust)

Code before:
    /// This method is like `with`, but it just calls `f` without setting the thread-local if that
    /// fails.
    fn with_if_possible<T>(&self, f: impl FnOnce() -> T) -> T {
        let mut f = Some(f);

        let res = CURRENT.try_with(|LocalData { ctx, entered, .. }| {
            struct Reset<'a> {
                ctx_ref: &'a RcCell<Context>,
                entered_ref: &'a Cell<bool>,
                ctx_val: Option<Rc<Context>>,
                entered_val: bool,
            }
            impl<'a> Drop for Reset<'a> {
                fn drop(&mut self) {
                    self.ctx_ref.set(self.ctx_val.take());
                    self.entered_ref.set(self.entered_val)
                }
            }
            let ctx_old = ctx.replace(Some(self.context.clone()));
            let entered_old = entered.replace(false);

            let _reset = Reset {
                ctx_ref: ctx,
                entered_ref: entered,
                ctx_val: ctx_old,
                entered_val: entered_old,
            };

            (f.take().unwrap())()
        });

        match res {
            Ok(res) => res,
            Err(_access_error) => (f.take().unwrap())(),
        }
    }
}

cfg_unstable! {
    impl LocalSet {
        /// Configure how the `LocalSet` responds to an unhandled panic on a
        /// spawned task.
        ///
        /// By default, an unhandled panic (i.e. a panic not caught by
        /// [`std::panic::catch_unwind`]) has no impact on the `LocalSet`'s
        /// execution. The panic is error value is forwarded to the task's
        /// [`JoinHandle`] and all other spawned tasks continue running.
        ///
        /// The `unhandled_panic` option enables configuring this behavior.
        ///
        /// * `UnhandledPanic::Ignore` is the default behavior. Panics on

Review comment (suggestion):
take it or leave it: the `Reset` code got substantially more complex in this change, and it's used in two different places. now that it's no longer fairly trivial, what do you think about moving this out of the `with` and `with_if_possible` functions, so that we can use one implementation in both places. Something like:
```rust
impl LocalData {
    fn enter(&self, context: Rc<Context>) -> Reset<'_> {
        let ctx_val = self.ctx.replace(Some(context));
        let entered_val = self.entered.replace(false);

        Reset {
            ctx_ref: self.ctx,
            entered_ref: self.entered,
            ctx_val: ctx_old,
            entered_val: entered_old,
        }
    }
}

struct Reset<'a> {
    ctx_ref: &'a RcCell<Context>,
    entered_ref: &'a Cell<bool>,
    ctx_val: Option<Rc<Context>>,
    entered_val: bool,
}

impl<'a> Drop for Reset<'a> {
    fn drop(&mut self) {
        self.ctx_ref.set(self.ctx_val.take());
        self.entered_ref.set(self.entered_val)
    }
}
```

and then changing `with` and `with_if_possible` to just call
```rust
let _reset = local_data.enter(self.context.clone());
```

Code after:
                    .and_then(|queue| queue.pop_front())
            })
        };

        task.map(|task| unsafe {
            // Safety: because the `LocalSet` itself is `!Send`, we know we are
            // on the same thread if we have access to the `LocalSet`, and can
            // therefore access the local run queue.
            self.context.shared.local_state.assert_owner(task)
        })
    }

    fn pop_local(&self) -> Option<task::Notified<Arc<Shared>>> {
        unsafe {
            // Safety: because the `LocalSet` itself is `!Send`, we know we are
            // on the same thread if we have access to the `LocalSet`, and can
            // therefore access the local run queue.
            self.context.shared.local_state.task_pop_front()
        }
    }

    fn with<T>(&self, f: impl FnOnce() -> T) -> T {
        CURRENT.with(|local_data| {
            let _guard = local_data.enter(self.context.clone());
            f()
        })
    }

    /// This method is like `with`, but it just calls `f` without setting the thread-local if that
    /// fails.
    fn with_if_possible<T>(&self, f: impl FnOnce() -> T) -> T {
        let mut f = Some(f);

        let res = CURRENT.try_with(|local_data| {
            let _guard = local_data.enter(self.context.clone());
            (f.take().unwrap())()
        });

        match res {
            Ok(res) => res,
            Err(_access_error) => (f.take().unwrap())(),
        }
    }
}

cfg_unstable! {
    impl LocalSet {
        /// Configure how the `LocalSet` responds to an unhandled panic on a
        /// spawned task.
        ///
        /// By default, an unhandled panic (i.e. a panic not caught by