execution_context/
data.rs1use im::hashmap::HashMap;
2use std::any::TypeId;
3use std::fmt;
4use std::hash::{BuildHasherDefault, Hasher};
5use std::mem;
6use std::sync::Arc;
7use std::ops::Deref;
8
9use ctx::ExecutionContext;
10
11#[macro_export]
19macro_rules! flow_local {
20 (static $NAME:ident : $t:ty = $e:expr) => {
21 static $NAME: $crate::FlowLocal<$t> = {
22 fn __init() -> $t {
23 $e
24 }
25 fn __key() -> ::std::any::TypeId {
26 struct __A;
27 ::std::any::TypeId::of::<__A>()
28 }
29 $crate::FlowLocal {
30 __init: __init,
31 __key: __key,
32 }
33 };
34 };
35}
36
37#[derive(Clone)]
42pub struct FlowBox<T: ?Sized>(Arc<Box<T>>);
43
44pub(crate) type LocalMap = HashMap<TypeId, Box<Opaque>, BuildHasherDefault<IdHasher>>;
45
46pub(crate) trait Opaque: Send + Sync {}
47impl<T: Send + Sync> Opaque for T {}
48
49pub struct FlowLocal<T> {
63 #[doc(hidden)]
66 pub __key: fn() -> TypeId,
67 #[doc(hidden)]
68 pub __init: fn() -> T,
69}
70
71impl<T> fmt::Debug for FlowLocal<T> {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73 write!(f, "FlowLocal")
74 }
75}
76
77pub(crate) struct IdHasher {
78 id: u64,
79}
80
81impl Default for IdHasher {
82 fn default() -> IdHasher {
83 IdHasher { id: 0 }
84 }
85}
86
87impl Hasher for IdHasher {
88 fn write(&mut self, _bytes: &[u8]) {
89 panic!("can only hash u64");
91 }
92
93 fn write_u64(&mut self, u: u64) {
94 self.id = u;
95 }
96
97 fn finish(&self) -> u64 {
98 self.id
99 }
100}
101
102impl<T: Send + 'static> FlowLocal<T> {
103 pub fn get(&self) -> FlowBox<T> {
111 let key = (self.__key)();
112
113 if let Some(rv) = ExecutionContext::get_local_value(key) {
114 return unsafe { mem::transmute(rv) };
115 };
116
117 let arc = Arc::new(Box::new((self.__init)()));
118 ExecutionContext::set_local_value(key, unsafe {
119 mem::forget(arc.clone());
120 mem::transmute(arc.clone())
121 });
122 FlowBox(arc)
123 }
124
125 pub fn set(&self, value: T) {
127 let key = (self.__key)();
128 let arc = Arc::new(Box::new(value));
129 ExecutionContext::set_local_value(key, unsafe {
130 mem::forget(arc.clone());
131 mem::transmute(arc.clone())
132 });
133 }
134}
135
136impl<T: fmt::Display + ?Sized> fmt::Display for FlowBox<T> {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 fmt::Display::fmt(&**self, f)
139 }
140}
141
142impl<T: fmt::Debug + ?Sized> fmt::Debug for FlowBox<T> {
143 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144 fmt::Debug::fmt(&**self, f)
145 }
146}
147
148impl<T: ?Sized> fmt::Pointer for FlowBox<T> {
149 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
150 let ptr: *const T = &**self;
153 fmt::Pointer::fmt(&ptr, f)
154 }
155}
156
157impl<T: ?Sized> Deref for FlowBox<T> {
158 type Target = T;
159
160 fn deref(&self) -> &T {
161 &*self.0
162 }
163}