Skip to content
Kavachकवच

No Data Races

● Advanced4 minBefore this: Tasks, Values, Not ReferencesSpec 9.5

Each task works on its own copy of a value, so two tasks can't change the same thing at once. To share on purpose, use Shared.

A lambda, and so each task, gets its own copy of count. Changing the copy doesn't change the outside one, and the compiler warns about it:

fn main() {
    let count = 0
    const _ = [1, 2, 3].parallel_map(n => {
        count += 1
        n
    })
    print(count)
}

The compiler warned, then the program ran:

kavach run copy.kav

warning: `count` is a copy inside this lambda: the change doesn't reach the outside. Give the value back instead, or use `Shared` to share it (spec 3.3)0
copy.kav: Kavach code, then what running it prints

That is what makes data races impossible: there is nothing two tasks share by accident. To count across tasks, share the value on purpose with Shared, which locks for you:

fn main() {
    const visits = Shared(0)
    const _ = [1, 2, 3, 4, 5].parallel_map(n => {
        visits.update(v => v + 1)
        n
    })
    print(visits.get())
}

The program ran and printed:

kavach run shared.kav

5
shared.kav: Kavach code, then what running it prints

In most languages, two threads adding to one counter can lose updates, a bug that shows up only sometimes. In Kavach the only shared value is a Shared, and its update takes the lock itself: there is no "remember to lock". See Shared State.

What Kavach does for you

  • No data races

    Tasks can't change the same value at the same time: the compiler refuses code that could.

    spec 9.5