runmat_thread_local/
lib.rs1#[cfg(target_arch = "wasm32")]
2use std::cell::UnsafeCell;
3
4#[cfg(target_arch = "wasm32")]
5pub struct WasmTlsCell<T> {
6 init: fn() -> T,
7 value: UnsafeCell<Option<T>>,
8}
9
10#[cfg(target_arch = "wasm32")]
11impl<T> WasmTlsCell<T> {
12 pub const fn new(init: fn() -> T) -> Self {
13 Self {
14 init,
15 value: UnsafeCell::new(None),
16 }
17 }
18
19 fn ensure(&self) -> *mut T {
20 unsafe {
21 let slot = &mut *self.value.get();
22 if slot.is_none() {
23 *slot = Some((self.init)());
24 }
25 slot.as_mut().expect("runmat wasm TLS slot init failed") as *mut T
26 }
27 }
28
29 pub fn with<R>(&self, f: impl FnOnce(&T) -> R) -> R {
30 let ptr = self.ensure();
31 unsafe { f(&*ptr) }
32 }
33
34 pub fn with_mut<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
35 let ptr = self.ensure();
36 unsafe { f(&mut *ptr) }
37 }
38}
39
40#[cfg(target_arch = "wasm32")]
41unsafe impl<T> Sync for WasmTlsCell<T> {}
42
43#[cfg(not(target_arch = "wasm32"))]
44#[macro_export]
45macro_rules! runmat_thread_local {
46 ($(#[$meta:meta])* static $name:ident : $ty:ty = const { $init:expr }; $($rest:tt)*) => {
47 thread_local! {
48 $(#[$meta])*
49 static $name: $ty = const { $init };
50 }
51 $crate::runmat_thread_local! { $($rest)* }
52 };
53 ($(#[$meta:meta])* static $name:ident : $ty:ty = $init:expr; $($rest:tt)*) => {
54 thread_local! {
55 $(#[$meta])*
56 static $name: $ty = $init;
57 }
58 $crate::runmat_thread_local! { $($rest)* }
59 };
60 () => {};
61}
62
63#[cfg(target_arch = "wasm32")]
64#[macro_export]
65macro_rules! runmat_thread_local {
66 ($(#[$meta:meta])* static $name:ident : $ty:ty = const { $init:expr }; $($rest:tt)*) => {
67 $crate::runmat_thread_local! {
68 $(#[$meta])*
69 static $name : $ty = $init;
70 $($rest)*
71 }
72 };
73 ($(#[$meta:meta])* static $name:ident : $ty:ty = $init:expr; $($rest:tt)*) => {
74 $(#[$meta])*
75 static $name: $crate::WasmTlsCell<$ty> = {
76 fn init() -> $ty {
77 $init
78 }
79 $crate::WasmTlsCell::new(init)
80 };
81 $crate::runmat_thread_local! { $($rest)* }
82 };
83 () => {};
84}