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}
57