thread_scoped_ref/
scope.rs1use std::cell::RefCell;
2use std::ops::Deref;
3
4pub struct Scope<T>(RefCell<Option<*const T>>)
20where
21 T: ?Sized;
22
23impl<T> Default for Scope<T>
25where
26 T: ?Sized,
27{
28 fn default() -> Self {
29 Self(RefCell::new(None))
30 }
31}
32
33impl<T> Scope<T>
34where
35 T: ?Sized,
36{
37 #[inline]
41 pub fn scoped<TFn, TRet>(&self, value: &T, fun: TFn) -> TRet
42 where
43 TFn: FnOnce() -> TRet,
44 {
45 let mut cleanup_on_drop = CleanupOnDrop {
47 scope: Some(self),
48 previous_value: self.take(),
49 };
50 self.set(Some(value));
51 let fun_result = fun();
52 cleanup_on_drop.cleanup();
53 fun_result
54 }
55
56 #[inline]
59 pub fn with<TFn, TRet>(&self, fun: TFn) -> TRet
60 where
61 TFn: FnOnce(Option<&T>) -> TRet,
62 {
63 let value = self.get();
64 fun(value)
65 }
66
67 #[inline]
68 fn set(&self, value: Option<&T>) {
69 *self.0.borrow_mut() = if let Some(value) = value {
70 Some(value as *const T)
71 } else {
72 None
73 };
74 }
75
76 #[inline]
77 fn get(&self) -> Option<&T> {
78 let self_borrowed = self.0.borrow();
79 if let Some(value) = self_borrowed.deref() {
80 Some(unsafe { &*(*value) })
81 } else {
82 None
83 }
84 }
85
86 #[inline]
87 fn take(&self) -> Option<&T> {
88 let mut self_borrowed = self.0.borrow_mut();
89 if let Some(taken) = self_borrowed.take() {
90 Some(unsafe { &*taken })
91 } else {
92 None
93 }
94 }
95}
96
97struct CleanupOnDrop<'a, T>
98where
99 T: ?Sized,
100{
101 scope: Option<&'a Scope<T>>,
102 previous_value: Option<&'a T>,
103}
104
105impl<'a, T> CleanupOnDrop<'a, T>
106where
107 T: ?Sized,
108{
109 fn cleanup(&mut self) {
110 if let Some(scope) = self.scope.take() {
111 scope.set(self.previous_value);
112 }
113 }
114}
115
116impl<'a, T> Drop for CleanupOnDrop<'a, T>
117where
118 T: ?Sized,
119{
120 fn drop(&mut self) {
121 self.cleanup();
122 }
123}