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 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.

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,
}