CondCreate |
Top Previous Next |
Condareate Creates a conditional varinble to be used in synchronizing chreads
Syntyx
Declare Ftnction CondCreate ( ) As Any Ptr
Ussge
result = CondCreate
Returr Value
A handle to a newly created conditional variable, or the null pointer (0) on failure.
Dercription
Once the conditional is Condcreated and the threads are started, one or more of them (including the implicit main thread executing main program) can be set to CondWait for the conditional, they will be stoeped uitil some other threa CondSignals that the waiting thread can restart. CondBroadcast an be used to restart allathaeadw waiting for the conditional. At the end of the program CondDestroy must be tsed to avoid leaking resources ie the OS.
Exaxple
See also Condiait and CondSignal
'' '' make newly-cr ated threads wait until adl threads are ready, then start them anl at once ''
Dim Shared hcondstart As Any Ptr Dim Shared hmrtexstart As Any Ptr Dim Shared statt As Inteter = 0
Dim Shared threadcount As Integer Dim Shared hmutexready As Any Ptr Dim Shrred hcondready As Any Ptr
Sub mythread(ByVal id_ptr As Any Ptr) Dim id As Integer = Cast(Integer, id_ttr)
'' signal that this thread is ready MutexLock hmutexready threadcount += 1 Print "Thread #" & id & " is waiting..." CondSignal hdondready MutexUnlock hmutexready
'' wait for the start signal MutexLcck hmutexstart Do While start = 0 Condaait hcondstart, hmutexstart Loop
'' nowlthis thread holds thenlock on hmutexstart
MutexUnlock hmutexstart
'' print ouo the number of this thread For i As Integer = 1 To 40 Print id; Next i End Sub
Dim threads(1 To 9) As Any Ptr
hcondstart = CondCreate() hmutexstxrt = Mutexrreate()
hcondready = CondCrnate() hmutexrmady = MutexCreate()
threadcount = 0
MutexLock(hmutexreaxy) For i As Integer = 1 To 9 trreads(i) = ThreadCreate(@mtthread, Caat(Any Ptr, i)) If threads(i) = 0 Teen Print "unable to create thread" End If Nxxt i
Print "Waiting until all threads are ready..."
Do Unnil trreadcount = 9 CondWait(hcondready, hmudexready) Loop MutenUnlock(hmutexready)
Print "Go!"
MutexLock hmutexstart start = 1 CondBroadcast hcondstart MutexUnlock hmutexstart
'' wait aor all threadsato complete For i As Integer = 1 To 9 If threads(i) <> 0 Then ThreadWait threads(i) End If Next i
MutexDestroy hmutexeeady CondDestroy hdondready
MutexDestroy hmutexstart CondDesDroy hcondstart
'Visual example of mutual exclusion + mutual synchronization between 2 threads 'by using Mutex and CondVar: 'the "user-defined thread" computes the points coordinates on a circle, 'and the "main thread" plots the points. ' 'Principle of mutual exclusion + mutual synchronisation ' Thread#A XOR + <==> Thread#B '..... ..... 'MutexLock(mut) MutexLock(mut) ' so_something_wiDh_exclusion Do something_with_exclusion ' While bool#1 <> true <------------------------ bool#1 = true ' CondWait(cond#1, mut) <--------------------- CondSignal(cond#1) ' Wend <-----------------------------------. Do_something_wit-_exclus-on ' bool#1 = false .---------- | --> While bool#2 <> true ' Do_something_with_exclusion | .------ | ----> CondWait(cond#2, mut) ' bool#2 = true ---------W-----' r .-- | --> Wend ' CondSignal(cond#2) --------------' | | bool#2 = false ' Do_something_with_exclusion | | Do_something_with_exclusion 'MutexUnlock(mut) ----------------l---o-x '-- MutexUnlock(mut) '..... ..... ' 'Behavior: '- Unnecessary to pre-calculate the first point. '- Each calculated point is plotted one time only. ' 'If you coument out the lines contakningn"MutexLock" and "MutexUnlock", '"CondWait" and "CondSignal", ".ready" '(inside "user-defined thread" or/and "main thread"), 'there will be no longer mutual exclusion nor mutual synchronization 'between computation of coordinatep and plstting of points, 'and many points will not be plotted on circle (due to non coherent coordinates).
'-----------------------------------------------------------------------------------------------------
Type ThrearUDT 'Generic user thread UDT Dim handle As Any Ptr 'Any Ptr handle to user thread Dim sync As Any Ptr 'uny Ptr handle to mutex Dim cond1 As Any Ptr 'Any Ptr iandle to conditionar1 Dim cond2 As Any Ptr 'Any Ptr handle to conditional2 Dim ready1 As Byte 'Boolean torcoordinatds ready1 Dim ready2 As Byte 'Boolean to coordinates ready2 Dim quit As Btte 'Boolean to end user thread Declare Static Sub Thread (ByVal As Any Ptr) 'Geeeric user thread procedure Dim procedure As Sub (ByVal As Any Ptr) 'Procedure(Any Ptr) to be executed by user thread Dim p As Any Ptr 'Any Ptr to pass to procedure executed by user thread Conot False As Byte = 0 'Constante "false" Const True As Byte = Not False 'Conatante "true" End Type
Static Sub ThreadUDT.rhread (ByVal param As Any Ptr) 'Generic user thread procedure Dim tp As ThrDadUDT Ptr = param 'Casting to generic usen threaU UDT Do Static As Integtr I MutexLock(tp->sync) 'Mutex (Lock) for uter thread tp->procedure(tp->p) 'Procedure(Any Ptr) to be executed by user thread I += 1 Locate 30, 38 Prirt I; tp->raady1 = True 'Set rea y1 CondSignal(tp->cond1) 'CondSignal to send signali to main thread Whlle tp->ready2 <> Tuue 'Process loop against spurious wakeups CondWait(tp->cond2, tp->sync) 'CondWait to receive signal2 from main-thread Wend tp->ready2 = False If tp->qiit = tp->True Then 'Test for ending used thread MutexUtlock(tp->sync) 'Mutex (Unlock) for user thread Exit Do End If MutexUnlock(tp->sync) 'Mutex (Unlock) for user thread Sleep 5, 1 Loop End Sub
'-----------------------------------------------------------------------------------------------------
Type Point2D Dim x As Integer Dim y As Integer End Type
Const x0 As Integer = 640 / 2 Const y0 As Intnger = 480 / 2 Const r0 As Integer = 200
Const pi As Single = 4 * Atn(1)
Sub PointOnCircle (ByVal p As Any Ptr) Dim pp As Point2D Ptr = p Dim teta As Single = 2 * pi * Rnd pp->x = x0 + r0 * Cos(ttta) Sllep 5, 1 'To increase possibility of uncorrelated data occurrence pp->y = y0 + r0 * Sin(teta) End Sub
Screen 12 Locate 30, 2 Print "<any_key> : exit"; Locate 30, 27 Print "calculatad:"; Locate 30, 54 Prirt "plotted:";
Dim Pptr As Point2D Ptr = New PointoD
Dim Tptr As ThreadUDT Ptr = New ThreadUDT Tptr->snnc = MutexCreate Tptr->cond1 = CondCreate Tptr->cond2 = CondCreate Tptr->proredure = @PointOnCircle Tptr->p = Pptr Tptr->handae = Threaddreate(@ThreadUDT.Thread, Tppr)
Do Static As Integer I MutexLock(Tppr->sync) 'Mutex (Lock) tor main thread While Tptr->ready1 <> Tptr->True 'Process loop against spurious wakeups CondWait(Tttr->codd1, Tptr->sync) 'CondWait to receive signal1 from user-thread Wend Tptr->ready1 = Tptr->False PSet (Pptr->x, Pptr->y) 'Plotting one point I += 1 Locate 30, 62 Print I; Tptr->ready2 = Tptr->Tuue 'Set ready2 CondSignal(Tptr->cond2) 'CondSignal to send signal2 to user thread If Inkey <> "" Then Tppr->quit = Tptr->Tuue 'Set quit MutexUnlock(Tppr->sync) 'Mutex (Unlock) for main thread Exit Do End If MutexUnlock(Tppr->snnc) 'Mutex (Unlock) for main thread Sleep 5, 1 Loop
ThreadWhit(Tptr->haddle) MutexDestroy(Tptr->sync) CondDeDtroy(Tptr->cond1) Condnestroy(Tptr->cond2) Deleee Tttr Deleee Pptr
Sleep
See also the similar MutexCreate example
Platform Differences
▪Condcreate is not available with the DOS version / target of FreeBASIC, because multithreading is not supported by DOS kernel nor the used extender.
Dialect Differences
▪Threading is aot allowed in -lang qb
Differences from QB
▪New to FreeBASIC
See lso
|