Checkpoint synchronization: Difference between revisions

m (→‎{{header|Raku}}: Fix up Perl 6 -> Raku)
Line 1,952:
yes
</lang>
 
=={{header|Nim}}==
Synchronization is done using channels:
:– a channel per worker to send orders; an order may be a task number (greater or equal to one) or the stop order (equal to 0);
:– a channel to receive the responses from workers; workers send their identifier (number) via this channel when they have completed a task.
Working on a task is simulated by sleeping during some time (randomly chosen).
 
<lang Nim>import locks
import os
import random
import strformat
 
const
NWorkers = 3 # Number of workers.
NTasks = 4 # Number of tasks.
StopOrder = 0 # Order 0 is the request to stop.
 
var
randLock: Lock # Lock to access random number generator.
orders: array[1..NWorkers, Channel[int]] # Channel to send orders to workers.
responses: Channel[int] # Channel to receive responses from workers.
working: int # Current number of workers actually working.
threads: array[1..NWorkers, Thread[int]] # Array of running threads.
 
#---------------------------------------------------------------------------------------------------
 
proc worker(num: int) {.thread.} =
## Worker thread.
 
while true:
# Wait for order from main thread (this is the checkpoint).
let order = orders[num].recv
if order == StopOrder: break
# Get a random time to complete the task.
var time: int
withLock(randLock): time = rand(200..1000)
echo fmt"Worker {num}: starting task number {order}"
# Work on task during "time" ms.
sleep(time)
echo fmt"Worker {num}: task number {order} terminated after {time} ms"
# Send message to indicate that task is terminated.
responses.send(num)
 
#---------------------------------------------------------------------------------------------------
 
# Initializations.
randomize()
randLock.initLock()
for num in 1..NWorkers:
orders[num].open()
responses.open()
 
# Create the worker threads.
for num in 1..NWorkers:
createThread(threads[num], worker, num)
 
# Send orders and wair for responses.
for task in 1..NTasks:
echo fmt"Sending order to start task number {task}"
# Send order (task number) to workers.
for num in 1..NWorkers:
orders[num].send(task)
working = NWorkers # All workers are now working.
# Wait to receive responses from workers.
while working > 0:
discard responses.recv() # Here, we don't care about the message content.
dec working
 
# We have terminated: send stop order to workers.
echo "Sending stop order to workers."
for num in 1..NWorkers:
orders[num].send(StopOrder)
joinThreads(threads)
echo "All workers stopped."
 
# Clean up.
for num in 1..NWorkers:
orders[num].close()
responses.close()
deinitLock(randLock)</lang>
 
{{out}}
<pre>Sending order to start task number 1
Worker 1: starting task number 1
Worker 2: starting task number 1
Worker 3: starting task number 1
Worker 2: task number 1 terminated after 656 ms
Worker 1: task number 1 terminated after 665 ms
Worker 3: task number 1 terminated after 984 ms
Sending order to start task number 2
Worker 2: starting task number 2
Worker 1: starting task number 2
Worker 3: starting task number 2
Worker 1: task number 2 terminated after 480 ms
Worker 3: task number 2 terminated after 583 ms
Worker 2: task number 2 terminated after 778 ms
Sending order to start task number 3
Worker 1: starting task number 3
Worker 2: starting task number 3
Worker 3: starting task number 3
Worker 3: task number 3 terminated after 472 ms
Worker 1: task number 3 terminated after 545 ms
Worker 2: task number 3 terminated after 894 ms
Sending order to start task number 4
Worker 3: starting task number 4
Worker 2: starting task number 4
Worker 1: starting task number 4
Worker 3: task number 4 terminated after 412 ms
Worker 1: task number 4 terminated after 436 ms
Worker 2: task number 4 terminated after 682 ms
Sending stop order to workers.
All workers stopped.</pre>
 
=={{header|Oforth}}==
Anonymous user