Skip to main content

canic_memory/macros/
runtime.rs

1/// Register one eager-init body for execution during lifecycle bootstrap.
2///
3/// The body is registered during process startup and later runs synchronously
4/// after Canic has touched eager TLS and before the memory registry flush.
5#[macro_export]
6macro_rules! eager_init {
7    ($body:block) => {
8        const _: () = {
9            fn __canic_registered_eager_init_body() {
10                $body
11            }
12
13            #[ $crate::__reexports::ctor::ctor(anonymous, crate_path = $crate::__reexports::ctor) ]
14            fn __canic_register_eager_init() {
15                $crate::runtime::defer_eager_init(__canic_registered_eager_init_body);
16            }
17        };
18    };
19}
20
21/// Declare a thread-local static and schedule an eager initialization touch.
22///
23/// Expands to a `thread_local!` block and ensures the TLS slot is accessed
24/// during the eager-init phase so subsequent calls observe a fully
25/// initialized value.
26#[macro_export]
27macro_rules! eager_static {
28    ($vis:vis static $name:ident : $ty:ty = $init:expr;) => {
29        thread_local! {
30            $vis static $name: $ty = $init;
31        }
32
33        const _: () = {
34            fn __canic_touch_tls() {
35                $name.with(|_| {});
36            }
37
38            #[ $crate::__reexports::ctor::ctor(anonymous, crate_path = $crate::__reexports::ctor) ]
39            fn __canic_register_eager_tls() {
40                $crate::runtime::defer_tls_initializer(__canic_touch_tls);
41            }
42        };
43    };
44}