mutex_add
result = mutex_add(m, delta)
Input: m, delta · Output: result
What it is
Atomic read-modify-write in a single lock acquisition (unlike mutex_set(m, mutex_get(m) + delta), which would race). m is a Mutex handle whose current stored value must be numeric; delta (number, may be negative) is added to it in place. The one operation you want for a shared counter/accumulator across parallel for iterations.
Overloads
One call shape — this function is not overloaded.
| Code | Input | Output | Description |
result = mutex_add(m, delta) | m Mutexm is a Mutex handle whose current stored value must be numeric.delta numberdelta (number, may be negative) is added to it in place. | result number | Returns the new value (number) after the addition. |
Examples
From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.
counter = mutex(0)
parallel for i in 1 to 100
mutex_add(counter, 1)
end parallel
print("total {mutex_get(counter)}")
total 100
from specialized
counter = mutex(0)
parallel for i in 1 to 100
mutex_add(counter, 1) # atomic; 100 in, 100 out, no lost updates
end parallel
total = mutex_get(counter)
print(total) # 100
100
from concurrency
How it works
mutex_add(m, delta) — atomic read-modify-write: the read-then-write is a SINGLE lock acquisition, unlike mutex_set(m, mutex_get(m) + delta), which would race (two workers could both read the same starting value before either writes back, losing an update). This is the one operation you actually want for a shared counter/accumulator across parallel for iterations. Returns the new value. No update is ever lost, but which worker's add lands first is real scheduling nondeterminism, and float addition isn't associative — so for non-integer-exact deltas the final value is correct (right up to ordinary float-reordering error) but NOT bit-reproducible run-to-run or across RAYON_NUM_THREADS. reduction-order determinism..." 2026-08-24): the same seeded script's mutex_add-accumulated total differed in its low-order bits across otherwise-identical runs. Contrast with parallel for's own index-assignment merge (merge_parallel_iteration), which writes to independent slots and so stays bit-identical regardless of scheduling.
From the note above this builtin in the interpreter, where the reasoning was written down as it was built.