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