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                if option_env!("CANIC_SKIP_EAGER_INIT").is_none() {
11                    $body
12                }
13            }
14
15            #[ $crate::__reexports::ctor::ctor(anonymous, crate_path = $crate::__reexports::ctor) ]
16            fn __canic_register_eager_init() {
17                $crate::runtime::defer_eager_init(__canic_registered_eager_init_body);
18            }
19        };
20    };
21}
22
23/// Declare a thread-local static and schedule an eager initialization touch.
24///
25/// Expands to a `thread_local!` block and ensures the TLS slot is accessed
26/// during the eager-init phase so subsequent calls observe a fully
27/// initialized value.
28#[macro_export]
29macro_rules! eager_static {
30    ($vis:vis static $name:ident : $ty:ty = $init:expr;) => {
31        thread_local! {
32            $vis static $name: $ty = $init;
33        }
34
35        const _: () = {
36            fn __canic_touch_tls() {
37                $name.with(|_| {});
38            }
39
40            #[ $crate::__reexports::ctor::ctor(anonymous, crate_path = $crate::__reexports::ctor) ]
41            fn __canic_register_eager_tls() {
42                $crate::runtime::defer_tls_initializer(__canic_touch_tls);
43            }
44        };
45    };
46}