macro_rules! if_atomic { ( if atomic(8) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => { ... }; ( if atomic(16) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => { ... }; ( if atomic(32) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => { ... }; ( if atomic(64) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => { ... }; ( if atomic(ptr) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => { ... }; ( if atomic(bool) $($rest:tt)* ) => { ... }; ( if atomic(size) $($rest:tt)* ) => { ... }; ( if ! atomic( $t:tt ) { $($a:tt)* } $( else { $($b:tt)* } )? $( if $($rest:tt)* )? ) => { ... }; }
Expand description
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 for8
size
: alias forptr
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.
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,
}