Atomics
Atomic integer operations.
On this page
An atomic operation changes a number in one step that other threads cannot interrupt. Use it for counters and flags shared between threads; use a Lock when several values must change together (see Sharing data between threads).
Update a number#
atomic(target op value) applies the operation to target and returns the value it had before:
Valk
fn main() {
let count = 5
let before = atomic(count + 2)
println(before) // 5
println(count) // 7
atomic(count - 1)
atomic(count | 8)
println(count) // 14
}
The operators are +, -, &, | and ^. The target must be assignable: a variable, a global or a property. Integers and floats both work.
Load and store#
atomic_load(x) reads a value and atomic_store(x, value) writes it, each as one atomic step:
Valk
fn main() {
let ready = 0
atomic_store(ready, 1)
println(atomic_load(ready)) // 1
}
Count across threads#
A shared global is visible to every thread, and atomic keeps concurrent updates from getting lost:
Valk
use valk.thread
shared hits: int (0)
fn main() {
let workers = Array[thread.Thread[void]]{}
each 0 .. 4 {
workers.append(thread.start(fn() {
each 0 .. 1000 : atomic(hits + 1)
}) !!)
}
each workers as worker : worker.await()
println(hits) // 4000
}
Properties of atomic data#
Number properties of an atomic object can be updated the same way from any thread:
Valk
use valk.thread
class Stats {
requests: uint
}
fn main() {
let stats: atomic Stats = Stats {}
let worker = thread.start(fn() {
each 0 .. 100 : atomic(stats.requests + 1)
}) !!
worker.await()
println(stats.requests) // 100
}
