wasmer_wasix/state/handles/
thread_local.rs1#![cfg_attr(any(feature = "sys", feature = "sys-minimal"), allow(unused))]
2use std::cell::{Ref, RefCell, RefMut};
3use std::ops::{Deref, DerefMut};
4use std::{
5 collections::HashMap,
6 rc::Rc,
7 sync::atomic::{AtomicU64, Ordering},
8};
9
10use wasmer::Memory;
11
12use crate::WasiModuleTreeHandles;
13
14static LOCAL_INSTANCE_SEED: AtomicU64 = AtomicU64::new(1);
15thread_local! {
16 static THREAD_LOCAL_INSTANCE_HANDLES: RefCell<HashMap<u64, Rc<RefCell<WasiModuleTreeHandles>>>>
17 = RefCell::new(HashMap::new());
18}
19
20pub(crate) struct WasiInstanceGuard<'a> {
24 borrow: Ref<'static, WasiModuleTreeHandles>,
27 _pointer: &'a WasiInstanceHandlesPointer,
28 _inner: Rc<RefCell<WasiModuleTreeHandles>>,
29}
30impl Deref for WasiInstanceGuard<'_> {
31 type Target = WasiModuleTreeHandles;
32 fn deref(&self) -> &Self::Target {
33 self.borrow.deref()
34 }
35}
36
37pub(crate) struct WasiInstanceGuardMut<'a> {
42 borrow: RefMut<'static, WasiModuleTreeHandles>,
45 _pointer: &'a WasiInstanceHandlesPointer,
46 _inner: Rc<RefCell<WasiModuleTreeHandles>>,
47}
48impl Deref for WasiInstanceGuardMut<'_> {
49 type Target = WasiModuleTreeHandles;
50
51 fn deref(&self) -> &Self::Target {
52 self.borrow.deref()
53 }
54}
55impl DerefMut for WasiInstanceGuardMut<'_> {
56 fn deref_mut(&mut self) -> &mut Self::Target {
57 self.borrow.deref_mut()
58 }
59}
60
61#[derive(Debug, Default, Clone)]
67pub(crate) struct WasiInstanceHandlesPointer {
68 id: Option<u64>,
70}
71impl Drop for WasiInstanceHandlesPointer {
72 fn drop(&mut self) {
73 self.clear();
74 }
75}
76impl WasiInstanceHandlesPointer {
77 pub fn get(&self) -> Option<WasiInstanceGuard<'_>> {
78 self.id
79 .iter()
80 .filter_map(|id| {
81 THREAD_LOCAL_INSTANCE_HANDLES.with(|map| {
82 let map = map.borrow();
83 if let Some(inner) = map.get(id) {
84 let borrow: Ref<WasiModuleTreeHandles> = inner.borrow();
85 let borrow: Ref<'static, WasiModuleTreeHandles> =
86 unsafe { std::mem::transmute(borrow) };
87 Some(WasiInstanceGuard {
88 borrow,
89 _pointer: self,
90 _inner: inner.clone(),
91 })
92 } else {
93 None
94 }
95 })
96 })
97 .next()
98 }
99 pub fn get_mut(&self) -> Option<WasiInstanceGuardMut<'_>> {
100 self.id
101 .into_iter()
102 .filter_map(|id| {
103 THREAD_LOCAL_INSTANCE_HANDLES.with(|map| {
104 let map = map.borrow_mut();
105 if let Some(inner) = map.get(&id) {
106 let borrow: RefMut<WasiModuleTreeHandles> = inner.borrow_mut();
107 let borrow: RefMut<'static, WasiModuleTreeHandles> =
108 unsafe { std::mem::transmute(borrow) };
109 Some(WasiInstanceGuardMut {
110 borrow,
111 _pointer: self,
112 _inner: inner.clone(),
113 })
114 } else {
115 None
116 }
117 })
118 })
119 .next()
120 }
121 pub fn set(&mut self, val: WasiModuleTreeHandles) {
122 self.clear();
123
124 let id = LOCAL_INSTANCE_SEED.fetch_add(1, Ordering::SeqCst);
125 THREAD_LOCAL_INSTANCE_HANDLES.with(|map| {
126 let mut map = map.borrow_mut();
127 map.insert(id, Rc::new(RefCell::new(val)));
128 });
129 if let Some(old_id) = self.id.replace(id) {
130 Self::destroy(old_id)
131 }
132 }
133 #[allow(dead_code)]
134 pub fn clear(&mut self) {
135 if let Some(id) = self.id.take() {
136 Self::destroy(id)
137 }
138 }
139 fn destroy(id: u64) {
140 THREAD_LOCAL_INSTANCE_HANDLES.with(|map| {
141 let mut map = map.borrow_mut();
142 map.remove(&id);
143 })
144 }
145}
146
147pub(crate) struct WasiInstanceGuardMemory<'a> {
149 borrow: &'a Memory,
152 _guard: WasiInstanceGuard<'a>,
153}
154impl Deref for WasiInstanceGuardMemory<'_> {
155 type Target = Memory;
156 fn deref(&self) -> &Self::Target {
157 self.borrow
158 }
159}
160impl<'a> WasiInstanceGuard<'a> {
161 pub fn memory(self) -> WasiInstanceGuardMemory<'a> {
162 let borrow: &Memory = (*self).memory();
163 let borrow: &'a Memory = unsafe { std::mem::transmute(borrow) };
164 WasiInstanceGuardMemory {
165 borrow,
166 _guard: self,
167 }
168 }
169}