@atomic

The @atomic module provides lock-free atomic operations backed by hand-written assembly (ARM64 and x86_64). Compiler-only feature.

Import

import @atomic

64-bit Atomics

All pointer arguments must be ^int (pointer to int).

load()

(ptr ^int) -> int

Atomically loads a value.

mut x int = 42
mut val = atomic.load(addr(x))
println(val)  // 42

store()

(ptr ^int, val int)

Atomically stores a value.

atomic.store(addr(x), 100)

add()

(ptr ^int, val int) -> int

Atomically adds to a value. Returns the previous value.

mut prev = atomic.add(addr(x), 5)  // x becomes x+5, prev = old x

sub()

(ptr ^int, val int) -> int

Atomically subtracts from a value. Returns the previous value.

mut prev = atomic.sub(addr(x), 3)

exchange()

(ptr ^int, val int) -> int

Atomically swaps the value. Returns the previous value.

mut old = atomic.exchange(addr(x), 99)

cas()

(ptr ^int, expected int, desired int) -> bool

Compare-and-swap. If the current value equals expected, sets it to desired and returns true. Otherwise returns false.

mut success = atomic.cas(addr(x), 42, 100)  // Only swaps if x == 42

and()

(ptr ^int, val int) -> int

Atomic bitwise AND. Returns the previous value.


or()

(ptr ^int, val int) -> int

Atomic bitwise OR. Returns the previous value.


xor()

(ptr ^int, val int) -> int

Atomic bitwise XOR. Returns the previous value.


Spinlock

spinlock()

() -> SpinLock

Creates a new spinlock.

mut lk = atomic.spinlock()

spin_lock()

(lk SpinLock)

Acquires a spinlock (spins until acquired).


spin_trylock()

(lk SpinLock) -> bool

Tries to acquire a spinlock. Returns true if acquired, false if already held.


spin_unlock()

(lk SpinLock)

Releases a spinlock.


Memory Barrier

fence()

()

Full memory barrier (sequential consistency).

atomic.fence()

Example Program

import @atomic
import @threads

mut counter int = 0

do worker() {
    for i in range(0, 1000) {
        atomic.add(addr(counter), 1)
    }
}

do main() {
    mut t1 = threads.spawn(()worker)
    mut t2 = threads.spawn(()worker)

    threads.join(t1)
    threads.join(t2)

    mut final = atomic.load(addr(counter))
    println("Counter:", final)  // 2000
}