tokio/runtime/context/
scoped.rs

1use std::cell::Cell;
2use std::ptr;
3
4/// Scoped thread-local storage
5pub(super) struct Scoped<T> {
6    pub(super) inner: Cell<*const T>,
7}
8
9impl<T> Scoped<T> {
10    pub(super) const fn new() -> Scoped<T> {
11        Scoped {
12            inner: Cell::new(ptr::null()),
13        }
14    }
15
16    /// Inserts a value into the scoped cell for the duration of the closure
17    pub(super) fn set<F, R>(&self, t: &T, f: F) -> R
18    where
19        F: FnOnce() -> R,
20    {
21        struct Reset<'a, T> {
22            cell: &'a Cell<*const T>,
23            prev: *const T,
24        }
25
26        impl<T> Drop for Reset<'_, T> {
27            fn drop(&mut self) {
28                self.cell.set(self.prev);
29            }
30        }
31
32        let prev = self.inner.get();
33        self.inner.set(t as *const _);
34
35        let _reset = Reset {
36            cell: &self.inner,
37            prev,
38        };
39
40        f()
41    }
42
43    /// Gets the value out of the scoped cell;
44    pub(super) fn with<F, R>(&self, f: F) -> R
45    where
46        F: FnOnce(Option<&T>) -> R,
47    {
48        let val = self.inner.get();
49
50        if val.is_null() {
51            f(None)
52        } else {
53            unsafe { f(Some(&*val)) }
54        }
55    }
56}