open_coroutine_core/common/
macros.rs

1//! Check <https://www.rustwiki.org.cn/en/reference/introduction.html> for help information.
2
3/// Constructs an event at the trace level.
4#[allow(unused_macros)]
5#[macro_export]
6macro_rules! trace {
7    ($( $args:expr ),*) => {
8        #[cfg(all(debug_assertions, feature = "log"))]
9        tracing::trace!( $( $args ),* );
10    }
11}
12
13/// Constructs an event at the info level.
14#[allow(unused_macros)]
15#[macro_export]
16macro_rules! info {
17    ($( $args:expr ),*) => {
18        #[cfg(feature = "log")]
19        tracing::info!( $( $args ),* );
20    }
21}
22
23/// Constructs an event at the warn level.
24#[allow(unused_macros)]
25#[macro_export]
26macro_rules! warn {
27    ($( $args:expr ),*) => {
28        #[cfg(feature = "log")]
29        tracing::warn!( $( $args ),* );
30    }
31}
32
33/// Constructs an event at the error level.
34#[allow(unused_macros)]
35#[macro_export]
36macro_rules! error {
37    ($( $args:expr ),*) => {
38        #[cfg(feature = "log")]
39        tracing::error!( $( $args ),* );
40    }
41}
42
43/// Catch panic.
44#[macro_export]
45macro_rules! catch {
46    ($f:expr, $msg:expr, $arg:expr) => {
47        std::panic::catch_unwind(std::panic::AssertUnwindSafe($f)).map_err(|e| {
48            let message = if let Some(msg) = e.downcast_ref::<&'static str>() {
49                *msg
50            } else {
51                $msg.leak()
52            };
53            $crate::error!("{} failed with error:{}", $arg, message);
54            message
55        })
56    };
57}
58
59/// Fast impl `Display` trait for `Debug` types.
60#[allow(unused_macros)]
61#[macro_export]
62macro_rules! impl_display_by_debug {
63    ($struct_name:ident$(<$($generic1:tt $( : $trait_tt1: tt $( + $trait_tt2: tt)*)?),+>)?
64        $(where $(
65            $generic2:tt $( : $trait_tt3: tt $( + $trait_tt4: tt)*)?
66        ),+)?
67    ) => {
68        impl$(<$($generic1 $( : $trait_tt1 $( + $trait_tt2)*)?),+>)? std::fmt::Display
69            for $struct_name$(<$($generic1),+>)?
70        where
71            $struct_name$(<$($generic1),+>)?: std::fmt::Debug,
72            $($($generic2 $( : $trait_tt3 $( + $trait_tt4)*)?),+,)?
73        {
74            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75                std::fmt::Debug::fmt(self, f)
76            }
77        }
78    };
79}
80
81/// Fast impl `Current` for a type.
82/// This crate use `std` cause `#![no_std]` not support `thread_local!`.
83#[allow(unused_macros)]
84#[macro_export]
85macro_rules! impl_current_for {
86    (
87        $name:ident,
88        $struct_name:ident$(<$($generic:tt $( : $trait_tt1: tt $( + $trait_tt2: tt)*)?),+>)?
89    ) => {
90        thread_local! {
91            static $name: crossbeam_utils::atomic::AtomicCell<std::collections::VecDeque<*const std::ffi::c_void>> =
92                const { crossbeam_utils::atomic::AtomicCell::new(std::collections::VecDeque::new()) };
93        }
94
95        impl$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)? $struct_name$(<$($generic),+>)? {
96            /// Init the current.
97            pub(crate) fn init_current(current: &Self) {
98                $name.with(|s| unsafe {
99                    s.as_ptr()
100                        .as_mut()
101                        .unwrap_or_else(|| {
102                            panic!(
103                                "thread:{} init {} current failed",
104                                std::thread::current().name().unwrap_or("unknown"),
105                                stringify!($name)
106                            )
107                        })
108                        .push_front(core::ptr::from_ref(current).cast::<std::ffi::c_void>());
109                });
110            }
111
112            /// Get the current if has.
113            #[must_use]
114            #[allow(unreachable_pub)]
115            pub fn current<'current>() -> Option<&'current Self> {
116                $name.with(|s| unsafe {
117                    s.as_ptr()
118                        .as_ref()
119                        .unwrap_or_else(|| {
120                            panic!(
121                                "thread:{} get {} current failed",
122                                std::thread::current().name().unwrap_or("unknown"),
123                                stringify!($name)
124                            )
125                        })
126                        .front()
127                        .map(|ptr| &*(*ptr).cast::<Self>())
128                })
129            }
130
131            /// Clean the current.
132            pub(crate) fn clean_current() {
133                $name.with(|s| unsafe {
134                    _ = s.as_ptr()
135                        .as_mut()
136                        .unwrap_or_else(|| {
137                            panic!(
138                                "thread:{} clean {} current failed",
139                                std::thread::current().name().unwrap_or("unknown"),
140                                stringify!($name)
141                            )
142                        })
143                        .pop_front();
144                });
145            }
146        }
147    };
148}
149
150/// Fast impl common traits for `Named` types.
151/// Check <https://www.rustwiki.org.cn/en/reference/introduction.html> for help information.
152#[macro_export]
153macro_rules! impl_for_named {
154    ($struct_name:ident$(<$($generic:tt $( : $trait_tt1: tt $( + $trait_tt2: tt)*)?),+>)?) => {
155        $crate::impl_ord_for_named!($struct_name$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)?);
156        $crate::impl_hash_for_named!($struct_name$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)?);
157    };
158}
159
160/// Fast impl `Eq` for `Named` types.
161#[macro_export]
162macro_rules! impl_eq_for_named {
163    ($struct_name:ident$(<$($generic:tt $( : $trait_tt1: tt $( + $trait_tt2: tt)*)?),+>)?) => {
164        impl$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)? PartialEq<Self>
165            for $struct_name$(<$($generic),+>)?
166        {
167            fn eq(&self, other: &Self) -> bool {
168                self.name().eq(other.name())
169            }
170        }
171
172        impl$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)? Eq
173            for $struct_name$(<$($generic),+>)?
174        {
175        }
176    };
177}
178
179/// Fast impl `Ord` for `Named` types.
180#[macro_export]
181macro_rules! impl_ord_for_named {
182    ($struct_name:ident$(<$($generic:tt $( : $trait_tt1: tt $( + $trait_tt2: tt)*)?),+>)?) => {
183        $crate::impl_eq_for_named!($struct_name$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)?);
184
185        impl$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)? PartialOrd<Self>
186            for $struct_name$(<$($generic),+>)?
187        {
188            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
189                Some(self.cmp(other))
190            }
191        }
192
193        impl$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)? Ord
194            for $struct_name$(<$($generic),+>)?
195        {
196            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
197                self.name().cmp(other.name())
198            }
199        }
200    }
201}
202
203/// Fast impl `std::hash::Hash` for `Named` types.
204#[macro_export]
205macro_rules! impl_hash_for_named {
206    ($struct_name:ident$(<$($generic:tt $( : $trait_tt1: tt $( + $trait_tt2: tt)*)?),+>)?) => {
207        impl$(<$($generic $( : $trait_tt1 $( + $trait_tt2)*)?),+>)? std::hash::Hash
208            for $struct_name$(<$($generic),+>)?
209        {
210            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
211                self.name().hash(state)
212            }
213        }
214    }
215}