canic_memory/macros/runtime.rs
1/// Run `$body` during process start-up using `ctor`.
2///
3/// The macro expands to a `ctor` hook so eager TLS initializers can register
4/// their work before any canister lifecycle hooks execute. Prefer wrapping
5/// the body in a separate function for larger initializers to keep the hook
6/// simple.
7#[macro_export]
8macro_rules! eager_init {
9 ($body:block) => {
10 #[ $crate::export::ctor::ctor(anonymous, crate_path = $crate::export::ctor) ]
11 fn __canic_eager_init() {
12 $body
13 }
14 };
15}
16
17/// Declare a thread-local static and schedule an eager initialization touch.
18///
19/// Expands to a `thread_local!` block and ensures the TLS slot is accessed
20/// during the eager-init phase so subsequent calls observe a fully
21/// initialized value. Use this for caches that must exist before canister
22/// entry points run.
23#[macro_export]
24macro_rules! eager_static {
25 ($vis:vis static $name:ident : $ty:ty = $init:expr;) => {
26 thread_local! {
27 $vis static $name: $ty = $init;
28 }
29
30 // A simple wrapper function that forces TLS initialization.
31 fn __touch_tls() {
32 $name.with(|_| {});
33 }
34
35 $crate::eager_init!({
36 $crate::runtime::defer_tls_initializer(__touch_tls);
37 });
38 };
39}