Usage of Atomic, Monitor, and Timer

Usage of Atomic

In a multi-threaded program, atomic operations are performed for counting.

import std.sync.*
import std.time.*
import std.collection.*

let count = AtomicInt64(0)

main(): Int64 {
    let list = ArrayList<Future<Int64>>()

    /* Creates 1000 threads */
    for (_ in 0..1000) {
        let fut = spawn {
            sleep(Duration.millisecond) /* Sleeps for 1 millisecond */
            count.fetchAdd(1)
        }
        list.append(fut)
    }

    /* Waits for completion of all threads */
    for (f in list) {
        f.get()
    }

    var val = count.load()
    println("count = ${val}")
    return 0
}

Output:

count = 1000

Usage of Monitor

Example:

In different threads, Monitor is used to suspend and awaken threads.

import std.sync.*
import std.time.{Duration, DurationExtension}

var mon = Monitor()
var flag: Bool = true

main(): Int64 {
    let fut = spawn {
        mon.lock()
        while (flag) {
            println("New thread: before wait")
            mon.wait()
            println("New thread: after wait")
        }
        mon.unlock()
    }

    /* Sleep for 10 milliseconds so that the new thread can be executed */
    sleep(10 * Duration.millisecond)

    mon.lock()
    println("Main thread: set flag")
    flag = false
    mon.unlock()

    println("Main thread: notify")
    mon.lock()
    mon.notifyAll()
    mon.unlock()

    /* Wait for completion of the new thread */
    fut.get()
    return 0
}

Output:

New thread: before wait
Main thread: set flag
Main thread: notify
New thread: after wait

Usage of Timer

Example:

Timer is used to create one-off and repetitive tasks.

import std.sync.*
import std.time.{Duration, DurationExtension}

main(): Int64 {
    let count = AtomicInt8(0)

    Timer.once(50 * Duration.millisecond) { =>
        println("run only once")
        count.fetchAdd(1)
    }

    let timer = Timer.repeat(100 * Duration.millisecond, 200 * Duration.millisecond, { =>
        println("run repetitively")
        count.fetchAdd(10)
    })

    sleep(Duration.second)
    timer.cancel()
    sleep(500 * Duration.millisecond)
    println("count = ${count.load()}")
    0
}

Output:

run only once
run repetitively
run repetitively
run repetitively
run repetitively
run repetitively
count = 51