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> { new() -> 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 set<F, R>(&self, t: &T, f: F) -> R where F: FnOnce() -> R,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; with<F, R>(&self, f: F) -> R where F: FnOnce(Option<&T>) -> R,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