Standard library · Time and concurrency

atomic

A counter and a flag that several threads can change safely without taking a lock by hand.

import atomic
On this page
  1. Types
  2. Functions

For a simple counter that several threads increment, you do not have to build a lock yourself: I64 in this package does each operation in one indivisible step. CompareAndSwap is the base of most lock-free algorithms: it changes the value only if it is still the one you expected.

In the current implementation each cell is protected by a small lock, so it is correct, but no faster than the processor's atomic instructions.

Types

I64

struct I64
A 64-bit whole number shared between threads.
NameTypeDescription
celli64*The address of the value.
musync.MutexThe internal lock.
atomic-I64.salam
import atomic

mut counter := atomic.I64 {}

func worker():
    repeat 1000:
        atomic.Add(counter, 1)
    end
end

func main:
    counter = atomic.NewI64(0)
    a := spawn(worker)
    b := spawn(worker)
    join(a)
    join(b)
    println atomic.Load(counter)
    atomic.Store(counter, 10)
    println atomic.Swap(counter, 20), atomic.Load(counter)
    println atomic.CompareAndSwap(counter, 20, 30), atomic.CompareAndSwap(counter, 20, 40), atomic.Load(counter)
    atomic.DestroyI64(counter)
    flag := atomic.NewFlag(false)
    println atomic.TestAndSet(flag), atomic.TestAndSet(flag), atomic.Get(flag)
    atomic.Set(flag, false)
    println atomic.Get(flag)
    atomic.DestroyFlag(flag)
end
Output2000 10 20 true false 30 true false true false

Flag

struct Flag
A true or false flag shared between threads.
NameTypeDescription
celli64*The address of the value.
musync.MutexThe internal lock.

The example for this item is shown with the ones above: atomic-I64.salam

Functions

NewI64

func NewI64(v: i64): I64
A new cell with an initial value.

The example for this item is shown with the ones above: atomic-I64.salam

Load

func Load(a: I64): i64
Reads the current value.

The example for this item is shown with the ones above: atomic-I64.salam

Store

func Store(a: I64, v: i64)
Writes a new value.

The example for this item is shown with the ones above: atomic-I64.salam

Add

func Add(a: I64, delta: i64): i64
Adds delta and returns the new value.

The example for this item is shown with the ones above: atomic-I64.salam

Swap

func Swap(a: I64, v: i64): i64
Writes a new value and returns the old one.

The example for this item is shown with the ones above: atomic-I64.salam

CompareAndSwap

func CompareAndSwap(a: I64, expected: i64, next: i64): bool
If the current value equals expected, sets it to next and returns true; otherwise it leaves it alone.

The example for this item is shown with the ones above: atomic-I64.salam

DestroyI64

func DestroyI64(a: I64)
Releases the cell.

The example for this item is shown with the ones above: atomic-I64.salam

NewFlag

func NewFlag(v: bool): Flag
A new flag with an initial value.

The example for this item is shown with the ones above: atomic-I64.salam

Get

func Get(f: Flag): bool
The flag's value.

The example for this item is shown with the ones above: atomic-I64.salam

Set

func Set(f: Flag, v: bool)
Sets the flag's value.

The example for this item is shown with the ones above: atomic-I64.salam

TestAndSet

func TestAndSet(f: Flag): bool
If the flag is off, turns it on and returns true; if it was already on, returns false. Only one thread wins.

The example for this item is shown with the ones above: atomic-I64.salam

DestroyFlag

func DestroyFlag(f: Flag)
Releases the flag.

The example for this item is shown with the ones above: atomic-I64.salam