Checkpoint synchronization: Difference between revisions

No edit summary
(→‎{{header|PureBasic}}: Added PureBasic)
Line 217:
A is ready
</pre>
=={{header|PureBasic}}==
PureBasic normally uses Semaphores and Mutex’s to synchronize parallel systems. This system only relies on semaphores between each thread and the controller (CheckPoint-procedure). For exchanging data a Mutex based message stack could easily be added, both synchronized according to this specific task or non-blocking if each worker could be allowed that freedom.
<lang PureBasic>#MaxWorktime=8000 ; "Workday" in msec
 
; Structure that each thread uses
Structure MyIO
ThreadID.i
Semaphore_Joining.i
Semaphore_Release.i
Semaphore_Deliver.i
Semaphore_Leaving.i
EndStructure
 
; Array of used threads
Global Dim Comm.MyIO(0)
 
; Master loop synchronizing the threads via semaphores
Procedure CheckPoint()
Protected i, j, maxthreads=ArraySize(Comm())
Protected Worker_count, Deliver_count
Repeat
For i=1 To maxthreads
With Comm(i)
If TrySemaphore(\Semaphore_Leaving)
Worker_count-1
ElseIf TrySemaphore(\Semaphore_Deliver)
Deliver_count+1
If Deliver_count=Worker_count
PrintN("All Workers reported in, starting next task.")
Deliver_count=0
For j=1 To maxthreads
SignalSemaphore(Comm(j)\Semaphore_Release)
Next j
EndIf
ElseIf TrySemaphore(\Semaphore_Joining)
PrintN("A new Worker joined the force.")
Worker_count+1: SignalSemaphore(\Semaphore_Release)
ElseIf Worker_count=0
ProcedureReturn
EndIf
Next i
EndWith
ForEver
StartAll=0
EndProcedure
 
; A worker thread, all orchestrated by the Checkpoint() routine
Procedure Worker(ID)
Protected EndTime=ElapsedMilliseconds()+#MaxWorktime, n
With Comm(ID)
SignalSemaphore(\Semaphore_Joining)
Repeat
Repeat ; Use a non-blocking semaphore check to avoid dead-locking at shutdown.
If ElapsedMilliseconds()>EndTime
SignalSemaphore(\Semaphore_Leaving)
PrintN("Thread #"+Str(ID)+" is done.")
ProcedureReturn
EndIf
Delay(1)
Until TrySemaphore(\Semaphore_Release)
n=Random(1000)
PrintN("Thread #"+Str(ID)+" will work for "+Str(n)+" msec.")
Delay(n): PrintN("Thread #"+Str(ID)+" delivering")
SignalSemaphore(\Semaphore_Deliver)
ForEver
EndWith
EndProcedure
 
; User IO & init
If OpenConsole()
Define i, j
Repeat
Print("Enter number of workers to use [2-2000]: ")
j=Val(Input())
Until j>=2 And j<=2000
ReDim Comm(j)
For i=1 To j
With Comm(i)
\Semaphore_Release =CreateSemaphore()
\Semaphore_Joining =CreateSemaphore()
\Semaphore_Deliver =CreateSemaphore()
\Semaphore_Leaving =CreateSemaphore()
\ThreadID = CreateThread(@Worker(),i)
EndWith
Next
PrintN("Work started, "+Str(j)+" workers has been called.")
CheckPoint()
Print("Press ENTER to exit"): Input()
EndIf</lang>
<pre style="height: 200px;overflow:scroll">Enter number of workers to use [2-2000]: 5
Work started, 5 workers has been called.
A new Worker joined the force.
A new Worker joined the force.
A new Worker joined the force.
A new Worker joined the force.
A new Worker joined the force.
Thread #5 will work for 908 msec.
Thread #3 will work for 405 msec.
Thread #1 will work for 536 msec.
Thread #2 will work for 632 msec.
Thread #4 will work for 202 msec.
Thread #4 delivering
Thread #3 delivering
Thread #1 delivering
Thread #2 delivering
Thread #5 delivering
All Workers reported in, starting next task.
Thread #2 will work for 484 msec.
Thread #4 will work for 836 msec.
Thread #5 will work for 464 msec.
Thread #3 will work for 251 msec.
Thread #1 will work for 734 msec.
Thread #3 delivering
Thread #5 delivering
Thread #2 delivering
Thread #1 delivering
Thread #4 delivering
All Workers reported in, starting next task.
Thread #3 will work for 864 msec.
Thread #1 will work for 526 msec.
Thread #5 will work for 145 msec.
Thread #2 will work for 762 msec.
Thread #4 will work for 283 msec.
Thread #5 delivering
Thread #4 delivering
Thread #1 delivering
Thread #2 delivering
Thread #3 delivering
All Workers reported in, starting next task.
Thread #2 will work for 329 msec.
Thread #4 will work for 452 msec.
Thread #1 will work for 176 msec.
Thread #5 will work for 702 msec.
Thread #3 will work for 500 msec.
Thread #1 delivering
Thread #2 delivering
Thread #4 delivering
Thread #3 delivering
Thread #5 delivering
All Workers reported in, starting next task.
Thread #5 will work for 681 msec.
Thread #3 will work for 71 msec.
Thread #2 will work for 267 msec.
Thread #1 will work for 151 msec.
Thread #4 will work for 252 msec.
Thread #3 delivering
Thread #1 delivering
Thread #4 delivering
Thread #2 delivering
Thread #5 delivering
All Workers reported in, starting next task.
Thread #5 will work for 963 msec.
Thread #3 will work for 378 msec.
Thread #1 will work for 209 msec.
Thread #4 will work for 897 msec.
Thread #2 will work for 736 msec.
Thread #1 delivering
Thread #3 delivering
Thread #2 delivering
Thread #5 delivering
Thread #4 delivering
All Workers reported in, starting next task.
Thread #2 will work for 44 msec.
Thread #4 will work for 973 msec.
Thread #1 will work for 700 msec.
Thread #3 will work for 505 msec.
Thread #5 will work for 256 msec.
Thread #2 delivering
Thread #5 delivering
Thread #3 delivering
Thread #1 delivering
Thread #4 delivering
All Workers reported in, starting next task.
Thread #2 will work for 703 msec.
Thread #4 will work for 296 msec.
Thread #1 will work for 702 msec.
Thread #3 will work for 99 msec.
Thread #5 will work for 114 msec.
Thread #3 delivering
Thread #5 delivering
Thread #4 delivering
Thread #1 delivering
Thread #2 delivering
All Workers reported in, starting next task.
Thread #3 will work for 97 msec.
Thread #5 will work for 192 msec.
Thread #2 will work for 762 msec.
Thread #1 will work for 232 msec.
Thread #4 will work for 484 msec.
Thread #3 delivering
Thread #5 delivering
Thread #1 delivering
Thread #4 delivering
Thread #2 delivering
All Workers reported in, starting next task.
Thread #1 will work for 790 msec.
Thread #5 will work for 602 msec.
Thread #3 will work for 105 msec.
Thread #2 will work for 449 msec.
Thread #4 will work for 180 msec.
Thread #3 delivering
Thread #4 delivering
Thread #2 delivering
Thread #2 is done.
Thread #4 is done.
Thread #3 is done.
Thread #5 delivering
Thread #5 is done.
Thread #1 delivering
Thread #1 is done.
Press ENTER to exit</pre>
 
=={{header|Tcl}}==
Anonymous user