radium/macros.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
#[doc(hidden)]
#[macro_export]
#[cfg(radium_atomic_8)]
macro_rules! __radium_if_atomic_8 {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($a)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(radium_atomic_8))]
macro_rules! __radium_if_atomic_8 {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($b)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(radium_atomic_16)]
macro_rules! __radium_if_atomic_16 {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($a)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(radium_atomic_16))]
macro_rules! __radium_if_atomic_16 {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($b)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(radium_atomic_32)]
macro_rules! __radium_if_atomic_32 {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($a)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(radium_atomic_32))]
macro_rules! __radium_if_atomic_32 {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($b)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(radium_atomic_64)]
macro_rules! __radium_if_atomic_64 {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($a)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(radium_atomic_64))]
macro_rules! __radium_if_atomic_64 {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($b)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(radium_atomic_ptr)]
macro_rules! __radium_if_atomic_ptr {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($a)* }
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(radium_atomic_ptr))]
macro_rules! __radium_if_atomic_ptr {
( [ $( $a:tt )* ] [ $( $b:tt )* ] ) => { $($b)* }
}
/// Conditional compilation based on the presence of atomic instructions.
///
/// This macro allows you to write `if`/`else` clauses, evaluated at
/// compile-time, that test the presence of atomic instructions and preserve or
/// destroy their guarded code accordingly.
///
/// The `if atomic(WIDTH)` test preserves the contents of its block when the
/// target architecture has atomic instructions for the requested `WIDTH`, and
/// removes them from the syntax tree when the target does not. If an `else`
/// clause is provided, the contents of the `else` block are used as a
/// substitute when the `if` is destroyed.
///
/// This macro can be used in any position. When it is used in item or statement
/// position, it can contain multiple `if` clauses, and each will be evaluated
/// in turn. Expression and type positions can only accept exactly one code
/// span, and so may only have exactly one `if`/`else` clause. An `else` clause
/// is required here so that the macro will always expand to something; an empty
/// expansion is a parse error.
///
/// # Macro Syntax
///
/// The macro contents `if atomic() {} else {}` are part of the macro
/// invocation. Only the contents of the two blocks are actual Rust code.
///
/// The acceptable arguments to `atomic()` are:
///
/// - `8`
/// - `16`
/// - `32`
/// - `64`
/// - `ptr`
/// - `bool`: alias for `8`
/// - `size`: alias for `ptr`
///
/// In addition, the `atomic()` test can be inverted, as `!atomic()`, to reverse
/// the preserve/destroy behavior of the `if` and `else` blocks.
///
/// # Examples
///
/// This demonstrates the use of `if_atomic!` to produce multiple statements,
/// and then to produce a single type-name.
///
/// ```rust
/// radium::if_atomic! {
/// if atomic(size) { use core::sync::atomic::AtomicUsize; }
/// if !atomic(size) { use core::cell::Cell; }
/// }
///
/// struct RadiumRc<T: ?Sized> {
/// strong: radium::if_atomic! {
/// if atomic(ptr) { AtomicUsize }
/// else { Cell<usize> }
/// },
/// weak: radium::types::RadiumUsize,
/// data: T,
/// }
/// ```
#[macro_export]
macro_rules! if_atomic {
( if atomic(8) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => {
$crate::__radium_if_atomic_8! {
[ $($a)* ] [ $( $($b)* )? ]
}
$($crate::if_atomic! { if $($rest)* })?
};
( if atomic(16) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => {
$crate::__radium_if_atomic_16! {
[ $($a)* ] [ $( $($b)* )? ]
}
$( $crate::if_atomic! { if $($rest)* } )?
};
( if atomic(32) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => {
$crate::__radium_if_atomic_32! {
[ $($a)* ] [ $( $($b)* )? ]
}
$( $crate::if_atomic! { if $($rest)* } )?
};
( if atomic(64) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => {
$crate::__radium_if_atomic_64! {
[ $($a)* ] [ $( $($b)* )? ]
}
$( $crate::if_atomic! { if $($rest)* } )?
};
( if atomic(ptr) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => {
$crate::__radium_if_atomic_ptr! {
[ $($a)* ] [ $( $($b)* )? ]
}
$( $crate::if_atomic! { if $($rest)* } )?
};
( if atomic(bool) $($rest:tt)* ) => {
$crate::if_atomic! { if atomic(8) $($rest)* }
};
( if atomic(size) $($rest:tt)* ) => {
$crate::if_atomic! { if atomic(ptr) $($rest)* }
};
( if ! atomic( $t:tt ) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => {
$crate::if_atomic! {
if atomic($t) { $( $($b)* )? } else { $($a)* } $( if $($rest)* )?
}
};
}