| 1 | use std::cell::Cell; |
| 2 | use std::ptr; |
| 3 | |
| 4 | /// Scoped thread-local storage |
| 5 | pub(super) struct Scoped<T> { |
| 6 | pub(super) inner: Cell<*const T>, |
| 7 | } |
| 8 | |
| 9 | impl<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 | } |
| 57 | |