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