init_hook/lib.rs
1#![no_std]
2extern crate self as init_hook;
3
4#[doc(hidden)]
5#[path = "private.rs"]
6pub mod __private;
7
8pub use init_hook_macros::call_on_init;
9
10#[doc(hidden)]
11pub use linkme;
12
13/// Call all functions registered by [call_on_init]
14///
15/// # Example
16///
17/// ```
18/// use std::sync::atomic::{AtomicBool, Ordering};
19/// static INIT_CALLED: AtomicBool = AtomicBool::new(false);
20///
21/// #[init_hook::call_on_init]
22/// fn init() {
23/// INIT_CALLED.store(true, Ordering::Release);
24/// }
25///
26/// fn main() {
27/// init_hook::init!();
28/// assert!(INIT_CALLED.load(Ordering::Acquire));
29/// }
30/// ```
31///
32/// # Panic
33///
34/// If init isn't used in main exactly once, `init_hook` will detect this and panic pre-main
35///
36/// ```should_panic
37/// use std::sync::atomic::{AtomicBool, Ordering};
38/// static INIT_CALLED: AtomicBool = AtomicBool::new(false);
39///
40/// #[init_hook::call_on_init]
41/// fn init() {
42/// INIT_CALLED.store(true, Ordering::Release);
43/// }
44///
45/// // This will panic with "`init_hook::init` must be used within the root main function"
46/// fn main() {
47/// let _init_called = INIT_CALLED.load(Ordering::Acquire);
48/// }
49/// ```
50#[macro_export]
51macro_rules! init {
52 () => {
53 #[cfg(not(test))]
54 {
55 if module_path!().contains("::") {
56 panic!("#[init_hook::init] can only be used in the crate root");
57 }
58 }
59
60 #[init_hook::linkme::distributed_slice(init_hook::__private::INIT)]
61 #[linkme(crate = init_hook::linkme)]
62 static INIT_CONFIGURED: bool = true;
63
64 unsafe {
65 init_hook::__private::call_init_fns();
66 }
67 };
68}