• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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