Help Center
Help CenterFreeBASIC

CondCreatefunction

Creates a conditional variable to be used in synchronizing threads

Threading Support Functionsfunctiondocumented

Syntax

Declare Function CondCreate ( ) As Any Ptr

Return value


A handle to a newly created conditional variable, or the null pointer (0) on failure.

Description


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 stopped until some other thread CondSignals that the waiting thread can restart. CondBroadcast can be used to restart all threads waiting for the conditional. At the end of the program CondDestroy must be used to avoid leaking resources in the OS.

Remarks

Usage


result = CondCreate

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


Differences from QB


  • New to FreeBASIC

See also


Example


See also CondWait and CondSignal and CondBroadcast

''

'' make newly-created threads wait until all threads are ready, then start them all at once

''



Dim Shared hcondstart As Any Ptr

Dim Shared hmutexstart As Any Ptr

Dim Shared start As Integer = 0



Dim Shared threadcount As Integer

Dim Shared hmutexready As Any Ptr

Dim Shared hcondready As Any Ptr



Sub mythread(ByVal id_ptr As Any Ptr)

    Dim id As Integer = Cast(Integer, id_ptr)

  

    '' signal that this thread is ready

    MutexLock hmutexready

    threadcount += 1

    Print "Thread #" & id & " is waiting..."

    CondSignal hcondready

    MutexUnlock hmutexready

   

    '' wait for the start signal

    MutexLock hmutexstart

    Do While start = 0   

        CondWait hcondstart, hmutexstart

    Loop



    '' now this thread holds the lock on hmutexstart

   

    MutexUnlock hmutexstart



    '' print out 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()

hmutexstart = MutexCreate()



hcondready = CondCreate()

hmutexready = MutexCreate()



threadcount = 0



MutexLock(hmutexready)

For i As Integer = 1 To 9

    threads(i) = ThreadCreate(@mythread, Cast(Any Ptr, i))

    If threads(i) = 0 Then

        Print "unable to create thread"

    End If

Next i



Print "Waiting until all threads are ready..."



Do Until threadcount = 9

    CondWait(hcondready, hmutexready)

Loop

MutexUnlock(hmutexready)



Print

Print "Go!"



MutexLock hmutexstart

start = 1

CondBroadcast hcondstart

MutexUnlock hmutexstart



'' wait for all threads to complete

For i As Integer = 1 To 9

    If threads(i) <> 0 Then

        ThreadWait threads(i)

    End If

Next i



MutexDestroy hmutexready

CondDestroy hcondready



MutexDestroy hmutexstart

CondDestroy 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)

'  Do_something_with_exclusion                    Do_something_with_exclusion

'  While bool#1 <> true <------------------------ bool#1 = true

'    CondWait(cond#1, mut) <--------------------- CondSignal(cond#1)

'  Wend <-----------------------------------.     Do_something_with_exclusion

'  bool#1 = false               .---------- | --> While bool#2 <> true

'  Do_something_with_exclusion  |   .------ | ----> CondWait(cond#2, mut)

'  bool#2 = true ---------------'   |   .-- | --> Wend

'  CondSignal(cond#2) --------------'   |   |     bool#2 = false

'  Do_something_with_exclusion          |   |     Do_something_with_exclusion

'MutexUnlock(mut) ----------------------'   '-- MutexUnlock(mut)

'.....                                          .....

'

'Behavior:

'- Unnecessary to pre-calculate the first point.

'- Each calculated point is plotted one time only.

'

'If you comment out the lines containing "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 coordinates and plotting of points,

'and many points will not be plotted on circle (due to non coherent coordinates).



'-----------------------------------------------------------------------------------------------------



Type ThreadUDT                                   'Generic user thread UDT

    Dim handle As Any Ptr                        'Any Ptr handle to user thread

    Dim sync As Any Ptr                          'Any Ptr handle to mutex

    Dim cond1 As Any Ptr                         'Any Ptr handle to conditional1

    Dim cond2 As Any Ptr                         'Any Ptr handle to conditional2

    Dim ready1 As Byte                           'Boolean to coordinates ready1

    Dim ready2 As Byte                           'Boolean to coordinates ready2

    Dim quit As Byte                             'Boolean to end user thread

    Declare Static Sub Thread (ByVal As Any Ptr) 'Generic 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

    Const False As Byte = 0                      'Constante "false"

    Const True As Byte = Not False               'Constante "true"

End Type



Static Sub ThreadUDT.Thread (ByVal param As Any Ptr) 'Generic user thread procedure

    Dim tp As ThreadUDT Ptr = param                  'Casting to generic user thread UDT

    Do

        Static As Integer I

        MutexLock(tp->sync)                          'Mutex (Lock) for user thread

        tp->procedure(tp->p)                         'Procedure(Any Ptr) to be executed by user thread

        I += 1

        Locate 30, 38

        Print I;

        tp->ready1 = True                            'Set ready1

        CondSignal(tp->cond1)                        'CondSignal to send signal1 to main thread

        While tp->ready2 <> True                     'Process loop against spurious wakeups

            CondWait(tp->cond2, tp->sync)            'CondWait to receive signal2 from main-thread

        Wend

        tp->ready2 = False

        If tp->quit = tp->True Then                  'Test for ending user thread

            MutexUnlock(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 Integer = 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(teta)

    Sleep 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 "calculated:";

Locate 30, 54

Print "plotted:";



Dim Pptr As Point2D Ptr = New Point2D



Dim Tptr As ThreadUDT Ptr = New ThreadUDT

Tptr->sync = MutexCreate

Tptr->cond1 = CondCreate

Tptr->cond2 = CondCreate

Tptr->procedure = @PointOnCircle

Tptr->p = Pptr

Tptr->handle = ThreadCreate(@ThreadUDT.Thread, Tptr)



Do

    Static As Integer I

    MutexLock(Tptr->sync)                 'Mutex (Lock) for main thread

    While Tptr->ready1 <> Tptr->True      'Process loop against spurious wakeups

        CondWait(Tptr->cond1, 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->True             'Set ready2

    CondSignal(Tptr->cond2)               'CondSignal to send signal2 to user thread

    If Inkey <> "" Then

        Tptr->quit = Tptr->True           'Set quit

        MutexUnlock(Tptr->sync)           'Mutex (Unlock) for main thread

        Exit Do

    End If

    MutexUnlock(Tptr->sync)               'Mutex (Unlock) for main thread

    Sleep 5, 1

Loop

 



ThreadWait(Tptr->handle)

MutexDestroy(Tptr->sync)

CondDestroy(Tptr->cond1)

CondDestroy(Tptr->cond2)

Delete Tptr

Delete Pptr



Sleep

See also the similar
MutexCreate example

Reference

  • Documented in KeyPgCondCreate.html