x.atomics #
v-atomics
Low-level atomic operations for V with explicit i386 support (MMX required on i386).
Native atomic primitives for V implemented with inline assembly, without relying on C FFI.
This repository is an experiment in providing low-level atomic operations directly in V, using V's inline assembly support.
At the moment, all operations provide sequentially consistent semantics.
Motivation
In the current V ecosystem, atomic operations are implemented via calls into C.
While this approach works, it introduces an additional dependency on the C toolchain and headers and limits control over the exact machine instructions being emitted.
x.atomics explores an alternative: native atomic operations implemented directly in V, using architecture-specific inline assembly and explicit semantics.
The current focus of this project is:
- correctness of basic atomic primitives;
- predictable and inspectable code generation;
- sequentially consistent behavior for all operations.
In future versions, the set of supported atomic operations will be expanded, and additional memory orderings will be introduced.
Scope and Guarantees
- atomic operations on integer types implemented in V with inline assembly;
- architecture-specific implementations (per-platform
atomics.<arch>.vfiles); - sequential consistency for all exposed operations.
Memory Model
All operations in this library are intended to be sequentially consistent:
- operations appear to be globally ordered;
- no weaker semantics (relaxed, acquire, release) are currently implemented;
- when weaker variants are added in the future, they will be explicitly named and documented.
Examples
See the examples directory for complete runnable examples.
Basic Usage
import x.atomics
fn main() {
mut value := i32(0)
// Atomically store a value
atomics.store_i32(&value, 42)
// Atomically load the value
loaded := atomics.load_i32(&value)
// Atomic add: returns the new value after addition
new_value := atomics.add_i32(&value, 10)
// Atomic swap: returns the old value
old := atomics.swap_i32(&value, 100)
}
Compare-and-Swap (CAS)
import x.atomics
fn main() {
mut flag := u32(0)
// CAS: if flag == 0, set it to 1; returns true on success
if atomics.cas_u32(&flag, 0, 1) {
println('Successfully changed flag from 0 to 1')
}
}
Available Operations
| Operation | i32 | i64 | u32 | u64 |
|---|---|---|---|---|
load_* |
yes | yes | yes | yes |
store_* |
yes | yes | yes | yes |
add_* |
yes | yes | yes | yes |
swap_* |
yes | yes | yes | yes |
cas_* |
yes | yes | yes | yes |
fn add_i32 #
fn add_i32(dest &i32, delta i32) i32
add_i32 atomically adds delta to the value at dest and returns the new value. The operation is performed with sequential consistency. Panics if dest is not 4-byte aligned.
fn add_i64 #
fn add_i64(dest &i64, delta i64) i64
add_i64 atomically adds delta to the value at dest and returns the new value. The operation is performed with sequential consistency. Panics if dest is not 8-byte aligned.
fn add_u32 #
fn add_u32(dest &u32, delta u32) u32
add_u32 atomically adds delta to the value at dest and returns the new value. The operation is performed with sequential consistency. Panics if dest is not 4-byte aligned.
fn add_u64 #
fn add_u64(dest &u64, delta u64) u64
add_u64 atomically adds delta to the value at dest and returns the new value. The operation is performed with sequential consistency. Panics if dest is not 8-byte aligned.
fn cas_i32 #
fn cas_i32(addr &i32, old i32, new i32) bool
cas_i32 performs a compare-and-swap operation. If the current value at addr equals old, it atomically stores new. Returns true if the swap was performed, false otherwise. The operation is performed with sequential consistency. Panics if addr is not 4-byte aligned.
fn cas_i64 #
fn cas_i64(addr &i64, old i64, new i64) bool
cas_i64 performs a compare-and-swap operation. If the current value at addr equals old, it atomically stores new. Returns true if the swap was performed, false otherwise. The operation is performed with sequential consistency. Panics if addr is not 8-byte aligned.
fn cas_u32 #
fn cas_u32(addr &u32, old u32, new u32) bool
cas_u32 performs a compare-and-swap operation. If the current value at addr equals old, it atomically stores new. Returns true if the swap was performed, false otherwise. The operation is performed with sequential consistency. Panics if addr is not 4-byte aligned.
fn cas_u64 #
fn cas_u64(addr &u64, old u64, new u64) bool
cas_u64 performs a compare-and-swap operation. If the current value at addr equals old, it atomically stores new. Returns true if the swap was performed, false otherwise. The operation is performed with sequential consistency. Panics if addr is not 8-byte aligned.
fn load_i32 #
fn load_i32(num &i32) i32
load_i32 atomically loads and returns the value at num. The operation is performed with sequential consistency. Panics if num is not 4-byte aligned.
fn load_i64 #
fn load_i64(num &i64) i64
load_i64 atomically loads and returns the value at num. The operation is performed with sequential consistency. Panics if num is not 8-byte aligned.
fn load_u32 #
fn load_u32(num &u32) u32
load_u32 atomically loads and returns the value at num. The operation is performed with sequential consistency. Panics if num is not 4-byte aligned.
fn load_u64 #
fn load_u64(num &u64) u64
load_u64 atomically loads and returns the value at num. The operation is performed with sequential consistency. Panics if num is not 8-byte aligned.
fn store_i32 #
fn store_i32(dest &i32, value i32)
store_i32 atomically stores value at dest. The operation is performed with sequential consistency. Panics if dest is not 4-byte aligned.
fn store_i64 #
fn store_i64(dest &i64, value i64)
store_i64 atomically stores value at dest. The operation is performed with sequential consistency. Panics if dest is not 8-byte aligned.
fn store_u32 #
fn store_u32(dest &u32, value u32)
store_u32 atomically stores value at dest. The operation is performed with sequential consistency. Panics if dest is not 4-byte aligned.
fn store_u64 #
fn store_u64(dest &u64, value u64)
store_u64 atomically stores value at dest. The operation is performed with sequential consistency. Panics if dest is not 8-byte aligned.
fn swap_i32 #
fn swap_i32(dest &i32, new i32) i32
swap_i32 atomically stores new value at dest and returns the old value. The operation is performed with sequential consistency. Panics if dest is not 4-byte aligned.
fn swap_i64 #
fn swap_i64(dest &i64, value i64) i64
swap_i64 atomically stores value at dest and returns the old value. The operation is performed with sequential consistency. Panics if dest is not 8-byte aligned.
fn swap_u32 #
fn swap_u32(dest &u32, new u32) u32
swap_u32 atomically stores new value at dest and returns the old value. The operation is performed with sequential consistency. Panics if dest is not 4-byte aligned.
fn swap_u64 #
fn swap_u64(dest &u64, value u64) u64
swap_u64 atomically stores value at dest and returns the old value. The operation is performed with sequential consistency. Panics if dest is not 8-byte aligned.