Atomic Operations (v0.2.2)
Atomic read-modify-write and compare-and-swap builtins (unstable).
Overview
The atomic builtins perform read-modify-write and compare-and-swap operations on a memory location. They map to the LLVM atomicrmw and cmpxchg instructions.
This feature is unstable. It only works when the compiler runs in unstable mode, and it can change or disappear.
Primary source: syntax/atomics/atomics.md
Syntax Signatures
fn example() void @public {
var atomicRelax counter: u32 = 10;
var old: u32 = atomicAdd(counter, 5);
}
Behavior and Use
The destination of an atomic operation must be a variable declared with an atomic ordering modificator, such as atomicRelax or atomicSync.
The operation inherits the ordering from the destination declaration. atomicNone and atomicFree do not describe an atomic operation and are rejected.
Compare-and-swap follows the C11 model: expected is passed by address and is updated with the current value on failure. The builtin returns true when the swap happened.
Read-Modify-Write Builtins
Each builtin writes a value atomically and returns the previous value. The destination and value must be integers.
atomicStore(counter, value)- stores a new value, returns the previous one.atomicAdd(counter, value)- addition.atomicSubtract(counter, value)- subtraction.atomicAnd(counter, value)- bitwise and.atomicNand(counter, value)- bitwise nand.atomicOr(counter, value)- bitwise or.atomicXor(counter, value)- bitwise xor.atomicSignedMaximum(counter, value)- signed maximum.atomicSignedMinimum(counter, value)- signed minimum.atomicUnsignedMaximum(counter, value)- unsigned maximum.atomicUnsignedMinimum(counter, value)- unsigned minimum.
Compare-And-Swap
atomicCompareAndSwap compares the destination against an expected value and swaps in a new value when they match.
- atomicCompareAndSwap(counter, expected, new, success, failure)
- expected is an lvalue holding the expected value; it is updated on failure.
- success and failure are atomic ordering arguments using the atomic keyword literals.
Example
fn main() s32 @public {
var atomicRelax counter: u32 = 20;
var expected: u32 = 20;
var swapped: bool = atomicCompareAndSwap(counter, expected, 30, atomicSync, atomicRelax);
if swapped && counter == 30 {
return 0;
}
return 1;
}
// Requires -mode unstable.
fn main() s32 @public {
var atomicRelax nextTicket: u32 = 100;
var ticket: u32 = atomicAdd(nextTicket, 1);
if ticket == 100 && nextTicket == 101 {
return 0;
}
return 1;
}