Revision history for ProPgMtCriticalSectionsFAQ


Revision [23928]

Last edited on 2020-02-25 14:19:30 by fxm [inserted a FAQ item on the 'Sleep' keyword usage in penultimate position]
Additions:
**""-""** Otherwise, the syntax ##//Sleep x, 1//## (inducing no internal test of key-press) is rather advised when there is no protection by mutual exclusion, which is very often the case in order to release time-slice for the other threads.
Deletions:
**""-""** Otherwise, the syntax ##//Sleep x, 1//## (inducing no internal test of key-press) is rather advised when there is no protection by mutual exclusion, which is very often the case to release time-slice for the other threads.


Revision [23927]

Edited on 2020-02-25 14:17:12 by fxm [inserted a FAQ item on the 'Sleep' keyword usage in penultimate position]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Is it better to take precautions when using the keyword 'Sleep' in threads?"}}**
{{fbdoc item="section" value="10. Is it better to take precautions when using the keyword 'Sleep' in threads?"}}
**""-""** Otherwise, the syntax ##//Sleep x, 1//## (inducing no internal test of key-press) is rather advised when there is no protection by mutual exclusion, which is very often the case to release time-slice for the other threads.
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Are there any precautions to take when using the keyword 'Sleep' in threads?"}}**
{{fbdoc item="section" value="10. Are there any precautions to take when using the keyword 'Sleep' in threads?"}}
**""-""** Otherwise, the syntax ##//Sleep x, 1//## (inducing no internal test of key-press) is rather advised when there is no protection by mutual exclusion, which is very often the case if one want to release time-slice for the other threads.


Revision [23926]

Edited on 2020-02-25 10:58:00 by fxm [inserted a FAQ item on the 'Sleep' keyword usage in penultimate position]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Are there any precautions to take when using the keyword 'Sleep' in threads?"}}**
{{fbdoc item="section" value="10. Are there any precautions to take when using the keyword 'Sleep' in threads?"}}
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Should one take precautions when using the keyword 'Sleep' in threads?"}}**
{{fbdoc item="section" value="10. Should one take precautions when using the keyword 'Sleep' in threads?"}}


Revision [23925]

Edited on 2020-02-25 07:19:56 by fxm [inserted a FAQ item on the 'Sleep' keyword usage in penultimate position]
Additions:
There is still some doubt about the perfect behavior of the keyword ##//Sleep//## in a multi-threading context.
It is therefore advisable to take the following precautions for its use:
**""-""** If it is absolutely necessary in a critical section of a thread, the syntax ##//Sleep x//## or ##//Sleep x, 0//##, because inducing an internal test of a key-press, must for greatest safety be preferably treated in the same way as the ##//Inkey//## keyword to avoid as much as possible any concurrent conflict with other threads.
**""-""** Otherwise, the syntax ##//Sleep x, 1//## (inducing no internal test of key-press) is rather advised when there is no protection by mutual exclusion, which is very often the case if one want to release time-slice for the other threads.
Deletions:
**""-""** If it is absolutely necessary in a critical section of a thread, ##//Sleep x//## or ##//Sleep x, 0//##, because inducing an internal test of a key-press, must for safety be preferably treated in the same way as the ##//Inkey//## keyword to avoid as much as possible any concurrent conflict with other threads.
**""-""** Otherwise, the ##//Sleep x, 1//## usage (inducing no internal test of key-press) is rather advised when there is no protection by mutual exclusion, which is very often the case if one want to release time-slice for the other threads.


Revision [23924]

Edited on 2020-02-25 03:52:37 by fxm [inserted a FAQ item on the 'Sleep' keyword usage in penultimate position]
Additions:
**""-""** Otherwise, the ##//Sleep x, 1//## usage (inducing no internal test of key-press) is rather advised when there is no protection by mutual exclusion, which is very often the case if one want to release time-slice for the other threads.
Deletions:
**""-""** Otherwise, the ##//Sleep x, 1//## usage (inducing no internal test of key-press) is rather advised if there is no protection by mutual exclusion, which is very often the case if one want to release time-slice for the other threads.


Revision [23923]

Edited on 2020-02-25 03:20:50 by fxm [inserted a FAQ item on the 'Sleep' keyword usage in penultimate position]
Additions:
**""-""** If it is absolutely necessary in a critical section of a thread, ##//Sleep x//## or ##//Sleep x, 0//##, because inducing an internal test of a key-press, must for safety be preferably treated in the same way as the ##//Inkey//## keyword to avoid as much as possible any concurrent conflict with other threads.
**""-""** Otherwise, the ##//Sleep x, 1//## usage (inducing no internal test of key-press) is rather advised if there is no protection by mutual exclusion, which is very often the case if one want to release time-slice for the other threads.
Deletions:
If it is absolutely necessary in a critical section of a thread, ##//Sleep x//## or ##//Sleep x, 0//##, because inducing an internal test of a key-press, must for safety be preferably treated in the same way as the ##//Inkey//## keyword to avoid as much as possible any concurrent conflict with other threads.
Otherwise, the ##//Sleep x, 1//## usage (inducing no internal test of key-press) is rather advised if there in no protection by mutual exclusion, which is very often the case if one want to release time-slice for the other threads.


Revision [23922]

Edited on 2020-02-25 02:50:43 by fxm [inserted a FAQ item on the 'Sleep' keyword usage in penultimate position]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Should one take precautions when using the keyword 'Sleep' in threads?"}}**
{{anchor name="ProPgMtCriticalSectionsFAQ10"}}
{{fbdoc item="section" value="10. Should one take precautions when using the keyword 'Sleep' in threads?"}}
If it is absolutely necessary in a critical section of a thread, ##//Sleep x//## or ##//Sleep x, 0//##, because inducing an internal test of a key-press, must for safety be preferably treated in the same way as the ##//Inkey//## keyword to avoid as much as possible any concurrent conflict with other threads.
Otherwise, the ##//Sleep x, 1//## usage (inducing no internal test of key-press) is rather advised if there in no protection by mutual exclusion, which is very often the case if one want to release time-slice for the other threads.


Revision [23921]

Edited on 2020-02-25 02:20:40 by fxm [renumbered items to insert a new]
Additions:
{{fbdoc item="section" value="11. Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?"}}
Deletions:
{{fbdoc item="section" value="10. Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?"}}


Revision [23920]

Edited on 2020-02-25 02:19:32 by fxm [renumbered items to insert a new]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ11|11. Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?"}}**
{{anchor name="ProPgMtCriticalSectionsFAQ11"}}
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?"}}**
{{anchor name="ProPgMtCriticalSectionsFAQ10"}}


Revision [23919]

Edited on 2020-02-24 08:38:22 by fxm [miscellaneous]
Additions:
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep x, 1' instruction in the 'While...Wend' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep x, 1' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
' SLEEP(tempo, 1)
But if 'Sleep x, 1' is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
' | Sleep my_tempo, 1
Sleep tempo, 1
%%Note: The ##//Sleep x, 1//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no screen locking is used.
%%Note: The ##//Sleep x, 1//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used.
%%Note: The ##//Sleep x, 1//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no two page flipping is used.
%%Note: The ##//Sleep x, 1//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used.
%%Note: The ##//Sleep x, 1//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used, or if no mutex is used.
%%Note: The ##//Sleep x, 1//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
%%Note: The ##//Sleep x, 1//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
Deletions:
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While...Wend' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
' SLEEP(tempo)
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
' | Sleep my_tempo
Sleep tempo
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no screen locking is used.
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used.
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no two page flipping is used.
%%Note: The Sleep keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used.
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used, or if no mutex is used.
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).


Revision [23889]

Edited on 2020-02-06 03:15:20 by fxm [wording]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ4|4. Why it is mandatory to put 'Condwait' within a 'While...Wend' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast', and reset after the 'Wend')?"}}**
{{fbdoc item="section" value="4. Why it is mandatory to put 'Condwait' within a 'While...Wend' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast', and reset after the 'Wend')?"}}
**""-""** So the predicate will already true before the receiving thread reaches the 'While...Wend' loop, inducing that ##//""CondWait""//## is downright skipped, so avoiding a definitive blocking phenomenon.
- Without a 'While...Wend' loop on predicate, the program hangs quickly (Ctrl-C to quit):
- With a 'While...Wend' loop on predicate around each ##//""CondWait""//##, no blocking phenomenon:
{{fbdoc item="section" value="4.1. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While...Wend' loop for checking a Boolean predicate set by other thread?"}}
' Principle of mutual exclusion + CONDWAIT in a While...Wend loop with predicate check, for a thread sub-section
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While...Wend' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
' Principle of mutual exclusion + SLEEP in a While...Wend loop with predicate check, for a thread sub-section
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ4|4. Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?"}}**
{{fbdoc item="section" value="4. Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?"}}
**""-""** So the predicate will already true before the receiving thread reaches the While loop, inducing that ##//""CondWait""//## is downright skipped, so avoiding a definitive blocking phenomenon.
- Without a While loop on predicate, the program hangs quickly (Ctrl-C to quit):
- With a While loop on predicate around each ##//""CondWait""//##, no blocking phenomenon:
{{fbdoc item="section" value="4.1. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}
' Principle of mutual exclusion + CONDWAIT in a While loop with predicate check, for a thread sub-section
' (connecting lines join the sender(s) and receiver( with predicateeach action occurring during the sequence)
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
' Principle of mutual exclusion + SLEEP in a While loop with predicate check, for a thread sub-section


Revision [23883]

Edited on 2020-02-02 07:21:08 by fxm [added example in paragraph 5]
Additions:
Locate row, cursor0
Locate row, cursor0
Deletions:
Locate row ,cursor0
Locate row ,cursor0


Revision [23882]

Edited on 2020-02-02 06:35:49 by fxm [added example in paragraph 5]
Additions:
If inputchr = Chr(27) Then 'Esc
Locate row ,cursor0
Print Space(Len(inputline) + 1);
inputline = ""
cursor = 0
If inputchr = Chr(27) Then 'Esc
Locate row ,cursor0
Print Space(Len(inputline) + 1);
inputline = ""
cursor = 0


Revision [23881]

Edited on 2020-02-02 02:43:49 by fxm [added example in paragraph 5]
Additions:
Sub Counter (ByVal pt As UDT Ptr) ' for a graphic character size 8x16
Sub Thread (ByVal p As Any Ptr) ' for a graphic character size 8x16


Revision [23880]

Edited on 2020-02-01 11:10:49 by fxm [added example in paragraph 5]
Additions:
Dim As Any Ptr img
Line .img, (0, 0)-(20 * 8 - 1, 16 - 1), 0, BF ' clearing the image buffer
Draw String .img, (0, 0), Str(.count) ' drawing in the image buffer
Put ((.number - 1) * 8, (.number - 1) * 16), .img, Pset ' copying the image buffer to screen
.img = ImageCreate(20 * 8, 16) ' using an image buffer to avoid flickering
ImageDestroy .img ' destroying the image buffer
Deletions:
Dim img As Any Ptr = ImageCreate(20 * 8, 16) ' using an image buffer to avoid flickering
.count += 1
Line img, (0, 0)-(20 * 8 - 1, 16 - 1), 0, BF ' clearing the image buffer
Draw String img, (0, 0), Str(.count) ' drawing in the image buffer
Put ((.number - 1) * 8, (.number - 1) * 16), img, Pset ' copying the image buffer to screen
ImageDestroy img ' destroying the image buffer


Revision [23879]

Edited on 2020-02-01 08:15:30 by fxm [added example in paragraph 5]
Additions:
Otherwise, by using only graphics keywords (using the only position of the graphic cursor) as ##//Line//##, ##//Draw String//##, ##//Put//## in the thread, induces a thread-safe procedure that is compatible with the ##//Line Input//## keyword in the main code with no mutex:
Deletions:
Otherwise, by using only graphics keywords (using the only position of the graphic cursor) as ##//Line//##, ##//Draw String//##, ##//Put//## in the threads, induces a thread-safe procedure that is compatible with the ##//Line Input//## keyword in the main code with no mutex:


Revision [23878]

Edited on 2020-02-01 03:28:08 by fxm [added example in paragraph 5]
Additions:
**Note:**
Otherwise, by using only graphics keywords (using the only position of the graphic cursor) as ##//Line//##, ##//Draw String//##, ##//Put//## in the threads, induces a thread-safe procedure that is compatible with the ##//Line Input//## keyword in the main code with no mutex:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5bis.bas"}}%%(freebasic)
Const As String prompt = "Enter ""quit"" for exit"
Dim img As Any Ptr = ImageCreate(20 * 8, 16) ' using an image buffer to avoid flickering
.count += 1
Line img, (0, 0)-(20 * 8 - 1, 16 - 1), 0, BF ' clearing the image buffer
Draw String img, (0, 0), Str(.count) ' drawing in the image buffer
Put ((.number - 1) * 8, (.number - 1) * 16), img, Pset ' copying the image buffer to screen
ImageDestroy img ' destroying the image buffer
Locate 8, 1, 0
Line Input; prompt; s
Locate , Len(prompt) + 3
Print Space(Len(s));
Loop Until LCase(s) = "quit"


Revision [23877]

Edited on 2020-01-31 06:29:45 by fxm [updated the examples of paragraph 5]
Additions:
Dim As Integer cursor
Dim As Integer cursor0
MutexLock(mutex)
r = CsrLin()
Print prompt & " _";
cursor0 = Pos() - 1
MutexUnlock(mutex)
MutexLock(mutex)
r = CsrLin()
If inputchr <> "" Then
If inputchr >= Chr(32) And inputchr < Chr(255) Then
inputline = Left(inputline, cursor) & inputchr & Mid(inputline, cursor + 1)
cursor += 1
ElseIf inputchr = Chr(08) And Cursor > 0 Then 'BkSp
cursor -= 1
inputline = Left(inputline, cursor) & Mid(inputline, cursor + 2)
Elseif inputchr = Chr(255) & "S" And Cursor < Len(inputline) Then 'Del
inputline = Left(inputline, cursor) & Mid(inputline, cursor + 2)
Elseif inputchr = Chr(255) + "M" AND Cursor < LEN(inputline) THEN 'Right
Cursor += 1
Elseif inputchr = Chr(255) + "K" AND Cursor > 0 THEN 'Left
Cursor -= 1
Locate row, cursor0
Print Left(inputline, cursor) & Chr(95) & Mid(inputline, cursor + 1) & " ";
MutexUnlock(mutex)
MutexLock(mutex)
r = CsrLin()
Locate row, cursor0
MutexUnlock(mutex)
Dim As Integer cursor
Dim As Integer cursor0
MutexLock(mutex)
r = CsrLin()
Print prompt & " _";
cursor0 = Pos() - 1
MutexUnlock(mutex)
MutexLock(mutex)
r = CsrLin()
If inputchr <> "" Then
If inputchr >= Chr(32) And inputchr < Chr(255) Then
inputline = Left(inputline, cursor) & inputchr & Mid(inputline, cursor + 1)
cursor += 1
ElseIf inputchr = Chr(08) And Cursor > 0 Then 'BkSp
cursor -= 1
inputline = Left(inputline, cursor) & Mid(inputline, cursor + 2)
Elseif inputchr = Chr(255) & "S" And Cursor < Len(inputline) Then 'Del
inputline = Left(inputline, cursor) & Mid(inputline, cursor + 2)
Elseif inputchr = Chr(255) + "M" AND Cursor < LEN(inputline) THEN 'Right
Cursor += 1
Elseif inputchr = Chr(255) + "K" AND Cursor > 0 THEN 'Left
Cursor -= 1
Locate row, cursor0
Print Left(inputline, cursor) & Chr(95) & Mid(inputline, cursor + 1) & " ";
MutexUnlock(mutex)
MutexLock(mutex)
r = CsrLin()
Locate row, cursor0
MutexUnlock(mutex)
Sub Counter (ByVal pt As UDT Ptr)
Sub Thread (ByVal p As Any Ptr)
MutexLock(.pMutex)
MutexUnlock(.pMutex)
UDT.pMutex = MutexCreate
u(I).pThread = ThreadCreate(@Thread, @u(I))
Loop Until LCase(threadInput(8, 1, """quit"" for exit?", 10, 1, UDT.pMutex)) = "quit"
ThreadWait(u(I).pThread)
MutexDestroy(UDT.pMutex)
Deletions:
r = Csrlin()
Print prompt & "? _";
r = Csrlin()
Locate row, column + Len(inputline) + Len(prompt) + 2
If Len(inputchr) = 1 Then
If Asc(inputchr) >= 32 Then
Print inputchr & Chr(95);
Locate , pos - 1
inputline &= inputchr
Elseif Asc(inputchr) = 08 and Len(inputline) > 0 Then
Locate , pos - 1
Print chr(95) & " ";
Locate , Pos() - 2
inputline = Left(inputline, Len(inputline) - 1)
r = Csrlin()
Locate row, column + Len(prompt) + 2
r = Csrlin()
Print prompt & "? _";
r = Csrlin()
Locate row, column + Len(inputline) + Len(prompt) + 2
If Len(inputchr) = 1 Then
If Asc(inputchr) >= 32 Then
Print inputchr & Chr(95);
Locate , pos - 1
inputline &= inputchr
Elseif Asc(inputchr) = 08 and Len(inputline) > 0 Then
Locate , pos - 1
Print chr(95) & " ";
Locate , Pos() - 2
inputline = Left(inputline, Len(inputline) - 1)
r = Csrlin()
Locate row, column + Len(prompt) + 2
Dim As Ulongint count
Sub Counter (Byval pt As UDT Ptr)
Mutexlock(.pMutex)
Mutexunlock(.pMutex)
UDT.pMutex = Mutexcreate
u(I).pThread = Threadcreate(@Thread, @u(I))
Loop Until Lcase(threadInput(8, 1, """quit"" for exit", 10, 1, UDT.pMutex)) = "quit"
Threadwait(u(I).pThread)
Mutexdestroy(UDT.pMutex)
Dim As Ulongint c
For I As Integer = 1 to UDT.numberMax
Print Culngint(c / t) & " increments per second"


Revision [23876]

Edited on 2020-01-29 10:02:51 by fxm [formatting]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ4.1|4.1. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}**
%%{{anchor name="ProPgMtCriticalSectionsFAQ4.1"}}
{{fbdoc item="section" value="4.1. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}**
%%{{anchor name="ProPgMtCriticalSectionsFAQ4b"}}
{{fbdoc item="section" value="4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.


Revision [23875]

Edited on 2020-01-28 13:00:09 by fxm [wording]
Additions:
**""-""** ##//Screenlock...Scrennunlock//## blocks are not compatible with multi-threading (otherwise, the program hangs). This is why a mutex block must be used around each such block to ensure the mutual exclusion.
- Example for a double buffering method (at each step, each thread needs to update the working page and copy it to the visible page, from within a mutual exclusion mutex code block):
**Note:** In these two examples, a mutual exclusion mutex code block is mandatory in the two threads, not only because of using console statements + ##//Inkey//##, but around also the graphics statements + ##//Screencopy//## only because of using double buffering method (without anti-flickering process, the graphics statements could be outside the exclusion mutex code block).
Since gfxlib2 is thread-safe, mutual mutex exclusion between threads is not necessary for the graphics statements themselves (including ##//Draw String//##).
- From the above example, if the date displaying and the time displaying are now two separate threads, a mutual exclusion mutex code block between these two threads is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two threads:
- Example showing that graphics statements (such as ##//Line//## and ##//Draw String//## and ##//Screencopy//##) in a thread (user thread here) can compete with console statements (such as ##//Locate//## and ##//Print//## and ##//Input//##) in another thread (main thread here), without using any mutual exclusion (by mutex):
- From the above example, if the date displaying and the time displaying are now two separate user threads, a mutual exclusion mutex code block between these two threads only is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two user threads only:
Deletions:
**""-""** ##//Screenlock...Scrennunlock//## blocks are not compatible with multi-threading (otherwise, the program hangs). This is why a mutex block must be used around each such block to ensure the exclusion.
- Example for a double buffering method (at each step, each thread needs to update the working page and copy it to the visible page, from within an exclusion mutex code block):
**Note:** In these two examples, an exclusion mutex code block is mandatory in the two threads, not only because of using console statements + ##//Inkey//##, but around also the graphics statements + ##//Screencopy//## only because of using double buffering method (without anti-flickering process, the graphics statements could be outside the exclusion mutex code block).
Since gfxlib2 is thread-safe, mutex exclusion between threads is not necessary for the graphics statements themselves (including ##//Draw String//##).
- From the above example, if the date displaying and the time displaying are now two separate threads, an exclusion mutex code block between these two threads is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two threads:
- Example showing that graphics statements (such as ##//Line//## and ##//Draw String//## and ##//Screencopy//##) in a thread (user thread here) can compete with console statements (such as ##//Locate//## and ##//Print//## and ##//Input//##) in another thread (main thread here), without using any exclusion (by mutex):
- From the above example, if the date displaying and the time displaying are now two separate user threads, an exclusion mutex code block between these two threads only is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two user threads only:


Revision [23646]

Edited on 2019-10-03 08:19:36 by fxm [wording]
Additions:
- [[ProPgMultiThreading|Multi-Threading Overview]]
Deletions:
- [[ProPgMultiThreading|Multi-Threading]]


Revision [23539]

Edited on 2019-09-24 02:56:14 by fxm [formatting]
Additions:
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------


Revision [23538]

Edited on 2019-09-24 00:04:23 by fxm [wording]
Additions:
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for the 3 'thread...()' member Subs, and static procedures for the 4 'mutex...()' member Subs and the 5 'cond...()' member Subs),
Deletions:
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for all 'thread...()', and static procedures for all 'mutex...()' and all 'cond...()'),


Revision [23534]

Edited on 2019-09-23 07:00:06 by fxm [formatting]
Additions:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <-----------------------------. .----> MutexLock(mut)
' While bool#1 <> true <---------------------- | --------. | Do_something_with_exclusion
' ( atomic_mutex_unlock(mut) ) ------. | '--------------- | ---- bool#1 = true
' CondWait(cond#1, mut) <----------- | --- | ------------------------ | ---- CondSignal(cond#1)
' ( atomic_mutex_re-lock(mut) ) <--- | ----'----. .--------------- | ---> While bool#2 <> true
' Wend | | | .---- | -------- ( atomic_mutex_unlock(mut) )
' bool#1 = false .------- | -------- | ---' .------ | --- |--------> CondWait(cond#2, mut)
' Do_something_with_exclusion | .--- | -------- | ------' .--- | ----'--------> ( atomic_mutex_re-lock(mut) )
' bool#2 = true ----------------' | | .--- | ---------' | Wend
' CondSignal(cond#2) ---------------' | | | | bool#2 = false
' Do_something_with_exclusion | | | | Do_something_with_exclusion
' MutexUnlock(mut) ----------------------'-----' '---------------'----------- MutexUnlock(mut)
' ..... .....
Deletions:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <-----------------------------. .---------> MutexLock(mut)
' While bool#1 <> true <---------------------- | ---. | Do_something_with_exclusion
' ( atomic_mutex_unlock(mut) ) ------. | '------- | --------- bool#1 = true
' CondWait(cond#1, mut) <----------- | --- | ----------- | --------- CondSignal(cond#1)
' ( atomic_mutex_re-lock(mut) ) <--- | ----| .------- | --------> While bool#2 <> true
' Wend | | | | .-------- ( atomic_mutex_unlock(mut) )
' bool#1 = false .------- | --- | ---' .--- | --- | ------> CondWait(cond#2, mut)
' Do_something_with_exclusion | .--- | --- | -------' |---- | ------> ( atomic_mutex_re-lock(mut) )
' bool#2 = true ----------------' | |---- | ------------' | Wend
' CondSignal(cond#2) ---------------' | | | bool#2 = false
' Do_something_with_exclusion | | | Do_something_with_exclusion
' MutexUnlock(mut) ----------------------' '-------------------'---- MutexUnlock(mut)
' ..... .....


Revision [23529]

Edited on 2019-09-23 02:01:43 by fxm [formatting]

No Differences

Revision [23527]

Edited on 2019-09-21 00:12:59 by fxm [formatting for .chm]

No Differences

Revision [23526]

Edited on 2019-09-21 00:11:55 by fxm [formatting for .chm]
Additions:







Revision [23505]

Edited on 2019-09-19 00:58:43 by fxm [formatting for .chm]
Additions:
@@**===='Critical sections' related questions====**@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
Function threadInput (ByVal row As Integer, ByVal column As Integer, ByRef prompt As String = "", _
ByVal sleeptime As Integer = 15, ByVal blank As Integer = 0, ByVal mutex As Any Ptr = 0 _
) As String
Function threadInput (ByVal row As Integer, ByVal column As Integer, ByRef prompt As String = "", _
ByVal sleeptime As Integer = 15, ByVal blank As Integer = 0, ByVal mutex As Any Ptr = 0 _
) As String
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
Deletions:
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
Function threadInput (Byval row As Integer, Byval column As Integer, Byref prompt As String = "", Byval sleeptime As Integer = 15, Byval blank As Integer = 0, Byval mutex As Any Ptr = 0) As String
Function threadInput (Byval row As Integer, Byval column As Integer, Byref prompt As String = "", Byval sleeptime As Integer = 15, Byval blank As Integer = 0, Byval mutex As Any Ptr = 0) As String
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}


Revision [23504]

Edited on 2019-09-19 00:36:57 by fxm [formatting for .chm]
Additions:
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
%%
%%
%%(freebasic)
%%
%%
%%
%%{{anchor name="ProPgMtCriticalSectionsFAQ4b"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
%%
%%
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)
%%
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no screen locking is used.
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-1.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-2.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no two page flipping is used.
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-1.bas"}}%%(freebasic)
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-2.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-3.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used, or if no mutex is used.
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
%%(freebasic)
%%Note: One can see that each thread does not write on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-1.bas"}}%%(freebasic)
%%Note: One can see that each thread writes now on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-2.bas"}}%%(freebasic)
%%Note: One can see that the foreground/background colors are not specific to the thread number (id between 1 and 9) on the console window, but this works great on the graphics window.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-3.bas"}}%%(freebasic)
%%Note: One can see that the foreground/background colors are now specific to the thread number (id between 1 and 9) on the console window (obviously this always works on the graphics window).
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-4.bas"}}%%(freebasic)
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-5.bas"}}%%(freebasic)
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq10-1.bas"}}%%(freebasic)
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}
Deletions:
@@**===='Critical sections' related questions====**@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
%%{{anchor name="ProPgMtCriticalSectionsFAQ4b"}}
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no screen locking is used.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-1.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-2.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no two page flipping is used.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-1.bas"}}%%(freebasic)
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-2.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-3.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used, or if no mutex is used.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
%%Note: One can see that each thread does not write on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-1.bas"}}%%(freebasic)
%%Note: One can see that each thread writes now on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-2.bas"}}%%(freebasic)
%%Note: One can see that the foreground/background colors are not specific to the thread number (id between 1 and 9) on the console window, but this works great on the graphics window.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-3.bas"}}%%(freebasic)
%%Note: One can see that the foreground/background colors are now specific to the thread number (id between 1 and 9) on the console window (obviously this always works on the graphics window).
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-4.bas"}}%%(freebasic)
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-5.bas"}}%%(freebasic)
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq10-1.bas"}}%%(freebasic)
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@


Revision [23503]

Edited on 2019-09-18 07:19:48 by fxm [formatting for .chm]
Additions:
The "**Critical Sections**" related questions in multi-threading.
Deletions:
The "**Critical Sections**" related questions.


Revision [23497]

Edited on 2019-09-18 00:35:41 by fxm [formatting for .chm]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}**
{{fbdoc item="section" value="1. When is it not mandatory to protect by a mutex one shared variable between several threads?"}}
{{fbdoc item="section" value="2. What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?"}}
{{fbdoc item="section" value="3. What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?"}}
{{fbdoc item="section" value="4. Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?"}}
{{fbdoc item="section" value="4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.
{{fbdoc item="section" value="5. How to implement a user input-line function fully thread-safe?"}}
{{fbdoc item="section" value="6. How to use 'Screenlock' with multi-threading?"}}
{{fbdoc item="section" value="7. How to use 'video paging (double buffering or page flipping)' with multi-threading?"}}
{{fbdoc item="section" value="8. How to use the FB runtime library for multi-threaded applications (gfxlib2) with multi-threading?"}}
{{fbdoc item="section" value="9. How to use console statements and keyboard inputs with multi-threading?"}}
{{fbdoc item="section" value="10. Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?"}}
A simple 'threadUDT' base Class can be defined as follows:
**""-""** with a private 'Any Ptr' non-static member field for each handle,
**""-""** with a private 'Any Ptr' static member field for one shared mutex,
**""-""** with a private 'Any Ptr' static member field for one shared conditional variable,
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for all 'thread...()', and static procedures for all 'mutex...()' and all 'cond...()'),
**""-""** with an abstract private 'Sub()' thread to be overridden by another 'Sub()' from inside the user derived Type (therefore its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).
- From the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Synchronous method example using a condwait then a condbroadcast (and a mutex) for all threads", now the user implementation is modified to be compatible with the base Class 'threadUDT':
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq10-1.bas"}}%%(freebasic)
Deletions:
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}
**1. __When is it not mandatory to protect by a mutex one shared variable between several threads?__**
**2. __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__**
**3. __What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?__**
**4. __Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?__**
4b. __Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?__
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
%%
%%
%%
%%
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
%%
%%
%%
%%
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.
**5. __How to implement a user input-line function fully thread-safe?__**
**6. __How to use 'Screenlock' with multi-threading?__**
**7. __How to use 'video paging (double buffering or page flipping)' with multi-threading?__**
**8. __How to use the FB runtime library for multi-threaded applications (gfxlib2) with multi-threading?__**
**9. __How to use console statements and keyboard inputs with multi-threading?__**
**10. __Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?__**
A simple 'threadUDT' base Class can be defined as follows:
**""-""** with a private 'Any Ptr' non-static member field for each handle,
**""-""** with a private 'Any Ptr' static member field for one shared mutex,
**""-""** with a private 'Any Ptr' static member field for one shared conditional variable,
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for all 'thread...()', and static procedures for all 'mutex...()' and all 'cond...()'),
**""-""** with an abstract private 'Sub()' thread to be overridden by another 'Sub()' from inside the user derived Type (therefore its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).
%%(freebasic)
- From the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Synchronous method example using a condwait then a condbroadcast (and a mutex) for all threads", now the user implementation is modified to be compatible with the base Class 'threadUDT':
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq10-1.bas"}}%%(freebasic)
%%


Revision [23496]

Edited on 2019-09-18 00:09:12 by fxm [formatting for .chm]
Additions:
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}
Deletions:
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}


Revision [23495]

Edited on 2019-09-18 00:05:57 by fxm [formatting for .chm]
Additions:
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
%%
%%
%%
%%
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
%%
%%
%%
%%
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.
Deletions:
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.


Revision [23494]

Edited on 2019-09-17 16:02:43 by fxm [formatting]
Additions:
""a) ""while another thread is waiting (within a While loop on predicate),
""b) ""before another thread is waiting (within a While loop on predicate).
Deletions:
a) while another thread is waiting (within a While loop on predicate),
b) before another thread is waiting (within a While loop on predicate).


Revision [23493]

Edited on 2019-09-17 15:33:24 by fxm [formatting]
Additions:
@@**===='Critical sections' related questions====**@@
Deletions:
**====@@'Critical sections' related questions@@====**


Revision [23492]

Edited on 2019-09-17 15:19:30 by fxm [formatting]
Additions:
**====@@'Critical sections' related questions@@====**
Deletions:
**===@@'Critical sections' related questions@@===**


Revision [23491]

Edited on 2019-09-17 15:11:15 by fxm [formatting]
Additions:
----
**===@@'Critical sections' related questions@@===**
{{anchor name="ProPgMtCriticalSectionsFAQ1"}}
**1. __When is it not mandatory to protect by a mutex one shared variable between several threads?__**
When accessing to shared variables between several threads, all their accesses must be generally put inside blocks ##//Mutexlock...Mutexunlock//##, in all threads:
**""-""** When the shared variable is only one simple predefined numeric type of ##//size <= sizeof(integer)//## (only one assembler instruction for access), the mutex use may be not mandatory.
**""-""** But if this is for example one shared variable ##//""LongInt""//## with a win32 compilation, it is advised here to use a mutex (otherwise the reading phase by a thread may be interlaced with the writing phase of another thread).
That is because to access a variable in memory (for reading or for writing), a processor uses its internal registers.
A N-bit processor has N-bit registers but none greater:
**""-""** So one only assembler instruction allows it to access a N-bit variable in memory.
**""-""** At opposite, to access a 2N-bit variable, it must use 2 assembler instructions.
**""-""** If between these two assembler instructions (for writing), another thread accesses this same variable (for reading), the got value may be incoherent (N-bit highest and N-bit lowest incoherent together).
This behavior can be checked with a graphic program using two threads and a shared ##//""LongInt""//## (64-bit) without mutex:
**""-""** by compiling in 32-bit, many read values are incoherent.
**""-""** by compiling in 64-bit, no read value is incoherent.
Compile the below test program:
**""-""** in 32-bit => Many erroneous points not on the circle but anywhere in the square containing the circle. If you uncomment the four lines 37/39/58/60 to activate the mutex, then all the got points are now on the circle only.
**""-""** in 64-bit => All points are valid, on the circle only, even if the mutex is not activated.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq1.bas"}}%%(freebasic)
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ2"}}
**2. __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__**
Chronology for one thread signaling which occurs:
a) while another thread is waiting (within a While loop on predicate),
b) before another thread is waiting (within a While loop on predicate).
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq2.bas"}}%%(freebasic)
Output part a - Chronology for Thread#1 signaling while Thread#0 is waiting:
Output part b - Chronology for Thread#1 signaling before Thread#0 is waiting:
**Note:** If ##//""CondWait""//## is not within a ##//While//## loop on predicate (by putting in comment the first line of above program), one can check in the second case (thread#1 signaling before thread#0 waiting), that thread#0 remains blocked in its waiting phase (Ctrl-C to quit).
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ3"}}
**3. __What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?__**
Referring to the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]##, one takes this opportunity to recall that:
**""-""** The mutex must always be also locked while executing ##//""Condsignal()""//## or ##//""Condbroadcast()""//## to wake up a thread (it may be unlocked but only after ##//""Condsignal()""//## or ##//""Condbroadcast()""//##).
**""-""** If the mutex is not locked (or even if the mutex is unlocked only just before executing ##//""Condsignal()""//## or ##//""Condbroadcast()""//##), the behavior may become unpredictable (it may work or not, depending on the threads configuration and execution real time).
In the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]## "Synchronous method example using a condwait then a condbroadcast (and a mutex) for all threads":
**""-""** If one at least ##//Mutexunlock()//## is moved just before its ##//""Condbroadcast()""//##, the program hangs very quickly.
**""-""** Although some users certify that the mutex can always be unlocked just before ##//""Condsignal()""//## or ##//""Condbroadcast()""//##, and others more cautious assert that one can do it only for a ##//""Condbroadcast()""//##, experiment shows the opposite!
The general rule is that:
**""-""** The condition must not be signaled (by ##//""Condsignal()""//## or ##//""Condbroadcast()""//##) between the time a thread locks the mutex and the time it waits on the condition variable (##//""CondWait()""//##), otherwise it seems that it may damage the waiting queue of threads on that condition variable.
**""-""** Thus to avoid that and follow this rule, it is necessary that the mutex remains locked when the condition is signaled.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ4"}}
**4. __Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?__**
**##//While predicate <> True
Condwait(conditionalid, mutexid)
predicate = False//##**

In all documentations, it is highly advisable to do so, mainly justified to fight against eventual spurious wake-ups.

This is probably true, but it is also advisable to do so to avoid to loose a ##//""CondSignal""//## (or ##//""CondBroadcast""//##) if it is prematurely activated while the receiving thread is not yet waiting on ##//""CondWait""//## (the signal is lost forever):
**""-""** In that case, the receiving thread has even not yet locked the mutex before that ##//""CondSignal""//## (or ##//""CondBroadcast""//##) is activated.
**""-""** So the predicate will already true before the receiving thread reaches the While loop, inducing that ##//""CondWait""//## is downright skipped, so avoiding a definitive blocking phenomenon.
Let two threads (thread #0 in main program, thread #1 in a user procedure, each that prints its number in a loop), having about the same execution time, and each one synchronizing the other in order to well interlace their numbers (by using one mutex, two condition variables and ##//""CondSignal""//##/##//""CondWait""//##):
- Without a While loop on predicate, the program hangs quickly (Ctrl-C to quit):
- With a While loop on predicate around each ##//""CondWait""//##, no blocking phenomenon:
%%{{anchor name="ProPgMtCriticalSectionsFAQ4b"}}
4b. __Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?__
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ5"}}
**5. __How to implement a user input-line function fully thread-safe?__**
The ##//Input//## keyword may be not thread-safe, when another thread must also access to input/output resource:
**""-""** When executing the ##//Input//## statement, the other running threads must not change the position of the text cursor, which prohibits instructions such as ##//Locate//##, ##//Print//##, ...
**""-""** Moreover, one cannot enclosed the ##//Input//## keyword inside a mutex locking (as we can do it for the ##//Inkey//## keyword), because while the inputting line would be not completed and validated, the other threads that want to also access to input/output would be fully blocked (waiting for mutex unlocking).
Thread-safe input-line function (versus input/output resource):
Input position, prompt message, sleeping time, line-blanking command, mutex pointer can be passed to the following ##//threadInput()//## function that simulates a simplified input function, but thread-safe, by using a looping around the ##//Inkey//## keyword (all input/output keywords must be enclosed inside a mutex locking block, and the cursor position must be restored at each mutex locking block ending):
- From the example 1 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Asynchronous method example using a mutex for all threads", now the running multi-threading code is waiting for the "quit" command in order to exit the program:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ6"}}
**6. __How to use 'Screenlock' with multi-threading?__**
**""-""** ##//Screenlock...Scrennunlock//## blocks are not compatible with multi-threading (otherwise, the program hangs). This is why a mutex block must be used around each such block to ensure the exclusion.
**""-""** The input keywords (like for keyboard, mouse) cannot be safely run when the screen is locked, therefore a such keyword must be outside of any ##//Screenlock...Screenunlock//## block, so outside any ##//Screenlock...Screenunlock//## block in its own thread, and protected of all ##//Screenlock...Screenunlock//## blocks of other threads by a mutex block. Therefore, ##//Getkey//## and ##//Input//##, the statements that wait for keypress or line input are unusable, but ##//Inkey//## that does not wait can work.

By applying some rules scrupulously, one can use ##//Screenlock//##/##//Screenunlock//## inside the threads.
Principle of coding for all threads including the main code (main thread):
- For example, it is mandatory to use one ##//Mutexlock...Mutexunlock//## block around each ##//Screenlock...Screenunlock//## block, and one other around the ##//Inkey//## instruction which itself must always be outside of any ##//Screenlock...Screenunlock//## bloc:
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no screen locking is used.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ7"}}
**7. __How to use 'video paging (double buffering or page flipping)' with multi-threading?__**
Instead of "screen locking" (see the above paragraph), "video paging (double buffering or page flipping)" can more simply be used with multi-threading, but be careful that many states in the gfxlib2 are thread-dependent like ##//Screenset//## (and also ##//View//## settings, graphic cursor position, graphic colors, ...).
Therefore, the setting for the working page and the visible page must always be controlled in each thread code which want to work with a multi-video page configuration.

- Example for a double buffering method (at each step, each thread needs to update the working page and copy it to the visible page, from within an exclusion mutex code block):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-1.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used.
- Example for a two page flipping method (at each step, each thread needs to update and flip, from within the same exclusion mutex code block, the two screen pages):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-2.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no two page flipping is used.
**Note:** In these two examples, an exclusion mutex code block is mandatory in the two threads, not only because of using console statements + ##//Inkey//##, but around also the graphics statements + ##//Screencopy//## only because of using double buffering method (without anti-flickering process, the graphics statements could be outside the exclusion mutex code block).

@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ8"}}
**8. __How to use the FB runtime library for multi-threaded applications (gfxlib2) with multi-threading?__**
The source code of gfxlib2 uses TLS (Thread Local Storage) to store many states, so many things are thread-specific.
Since gfxlib2 is thread-safe, mutex exclusion between threads is not necessary for the graphics statements themselves (including ##//Draw String//##).
In contrast, console statements such as ##//Locate//##, ##//Print//##, ... are not thread-safe as previously mentioned (for example, text cursor position is common to all threads).

- Simple example showing that graphic states (such as graphic cursor position, graphic colors) are thread-dependent:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-1.bas"}}%%(freebasic)
- Example showing that graphics statements (such as Line and Draw String and Screencopy) in a thread can compete with console statements (such as Inkey) in another thread, without using any exclusion (by mutex):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-2.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used.
- From the above example, if the date displaying and the time displaying are now two separate threads, an exclusion mutex code block between these two threads is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two threads:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-3.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used, or if no mutex is used.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ9"}}
**9. __How to use console statements and keyboard inputs with multi-threading?__**
Console statements (such as ##//Locate//##, ##//Print//##, ##//Color//##, ...), as well as ##//Locate//## and ##//Print//## on Graphics window (but not ##//Color//## on Graphics Window), and keyboard inputs (such as ##//Inkey//##, ##//Getkey//##, ##//Input//##, ...) are not thread-safe:
**""-""** Thus when they are used in competing sections of different threads, mutual exclusion is mandatory by means of mutex locking blocks in which in addition code can restore states (such as text cursor position, console color, ...) at end of the block (after its own usage), as they were before (at begin of the block).
**""-""** But the ##//Getkey//## or ##//Input//## keyword cannot be enclosed inside a mutex locking block (as it can be do with the ##//Inkey//## keyword), because as long as the keyboard input is not completed, the other threads in compete would be fully blocked (waiting for the mutex unlocking).
- Example showing that the keywords ##//Locate//## and ##//Print//## are not thread-safe both when applied on a console window or when applied on a graphics window (the text cursor states being not thread dependent in the two cases):
%%Note: One can see that each thread does not write on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.
- From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring cursor states before/after its own cursor moving:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-1.bas"}}%%(freebasic)
%%Note: One can see that each thread writes now on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.
- Example showing that the ##//Color//## keyword is not thread-safe when applied on a console window, but is thread-safe when applied on a graphics window (the color states being thread dependent in that case):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-2.bas"}}%%(freebasic)
%%Note: One can see that the foreground/background colors are not specific to the thread number (id between 1 and 9) on the console window, but this works great on the graphics window.
- From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring color states before/after its own color values usage:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-3.bas"}}%%(freebasic)
%%Note: One can see that the foreground/background colors are now specific to the thread number (id between 1 and 9) on the console window (obviously this always works on the graphics window).
Therefore, for using Getkey or Input in competing sections of threads:
**""-""** Only a single thread (for example, the main thread) can uses ##//Getkey//## or ##//Input//## in addition to console statements (such as ##//Locate//##, ##//Print//##, ##//Color//##, ...) and also ##//Inkey//##, in its competing sections.
**""-""** The other threads must not to use in their competing sections any console statement neither any keyboard input keyword, but can use by cons graphics statements (such as ##//Pset//##, ##//Line//##, ##//Circle//##, ##//Draw String//##, graphic ##//Color//##, ...) which are themselves thread-safe (they can interlace graphically with the main thread without any problem).
**""-""** ##//Input//## and ##//Getkey//## also exclude the screen locking usage in competing sections of threads (double buffering is recommended as anti-flickering method).
- Example showing that graphics statements (such as ##//Line//## and ##//Draw String//## and ##//Screencopy//##) in a thread (user thread here) can compete with console statements (such as ##//Locate//## and ##//Print//## and ##//Input//##) in another thread (main thread here), without using any exclusion (by mutex):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-4.bas"}}%%(freebasic)
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
- From the above example, if the date displaying and the time displaying are now two separate user threads, an exclusion mutex code block between these two threads only is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two user threads only:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-5.bas"}}%%(freebasic)
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ10"}}
**10. __Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?__**
A simple 'threadUDT' base Class can be defined as follows:
**""-""** with a private 'Any Ptr' non-static member field for each handle,
**""-""** with a private 'Any Ptr' static member field for one shared mutex,
**""-""** with a private 'Any Ptr' static member field for one shared conditional variable,
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for all 'thread...()', and static procedures for all 'mutex...()' and all 'cond...()'),
**""-""** with an abstract private 'Sub()' thread to be overridden by another 'Sub()' from inside the user derived Type (therefore its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).
%%(freebasic)
- From the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Synchronous method example using a condwait then a condbroadcast (and a mutex) for all threads", now the user implementation is modified to be compatible with the base Class 'threadUDT':
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq10-1.bas"}}%%(freebasic)
%%
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
Deletions:
----
**===@@'Critical sections' related questions@@===**
{{anchor name="ProPgMtCriticalSectionsFAQ1"}}
1) **__When is it not mandatory to protect by a mutex one shared variable between several threads?__**
When accessing to shared variables between several threads, all their accesses must be generally put inside blocks ##//Mutexlock...Mutexunlock//##, in all threads:
**""-""** When the shared variable is only one simple predefined numeric type of ##//size <= sizeof(integer)//## (only one assembler instruction for access), the mutex use may be not mandatory.
**""-""** But if this is for example one shared variable ##//""LongInt""//## with a win32 compilation, it is advised here to use a mutex (otherwise the reading phase by a thread may be interlaced with the writing phase of another thread).
That is because to access a variable in memory (for reading or for writing), a processor uses its internal registers.
A N-bit processor has N-bit registers but none greater:
**""-""** So one only assembler instruction allows it to access a N-bit variable in memory.
**""-""** At opposite, to access a 2N-bit variable, it must use 2 assembler instructions.
**""-""** If between these two assembler instructions (for writing), another thread accesses this same variable (for reading), the got value may be incoherent (N-bit highest and N-bit lowest incoherent together).
This behavior can be checked with a graphic program using two threads and a shared ##//""LongInt""//## (64-bit) without mutex:
**""-""** by compiling in 32-bit, many read values are incoherent.
**""-""** by compiling in 64-bit, no read value is incoherent.
Compile the below test program:
**""-""** in 32-bit => Many erroneous points not on the circle but anywhere in the square containing the circle. If you uncomment the four lines 37/39/58/60 to activate the mutex, then all the got points are now on the circle only.
**""-""** in 64-bit => All points are valid, on the circle only, even if the mutex is not activated.
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq1.bas"}}%%(freebasic)
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ2"}}
1) **__What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__**
Chronology for one thread signaling which occurs:
a) while another thread is waiting (within a While loop on predicate),
b) before another thread is waiting (within a While loop on predicate).
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq2.bas"}}%%(freebasic)
Output part a - Chronology for Thread#1 signaling while Thread#0 is waiting:
%%
%%
Output part b - Chronology for Thread#1 signaling before Thread#0 is waiting:
%%
%%
**Note:** If ##//""CondWait""//## is not within a ##//While//## loop on predicate (by putting in comment the first line of above program), one can check in the second case (thread#1 signaling before thread#0 waiting), that thread#0 remains blocked in its waiting phase (Ctrl-C to quit).
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ3"}}
1) **__What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?__**
Referring to the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]##, one takes this opportunity to recall that:
**""-""** The mutex must always be also locked while executing ##//""Condsignal()""//## or ##//""Condbroadcast()""//## to wake up a thread (it may be unlocked but only after ##//""Condsignal()""//## or ##//""Condbroadcast()""//##).
**""-""** If the mutex is not locked (or even if the mutex is unlocked only just before executing ##//""Condsignal()""//## or ##//""Condbroadcast()""//##), the behavior may become unpredictable (it may work or not, depending on the threads configuration and execution real time).
In the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]## "Synchronous method example using a condwait then a condbroadcast (and a mutex) for all threads":
**""-""** If one at least ##//Mutexunlock()//## is moved just before its ##//""Condbroadcast()""//##, the program hangs very quickly.
**""-""** Although some users certify that the mutex can always be unlocked just before ##//""Condsignal()""//## or ##//""Condbroadcast()""//##, and others more cautious assert that one can do it only for a ##//""Condbroadcast()""//##, experiment shows the opposite!
The general rule is that:
**""-""** The condition must not be signaled (by ##//""Condsignal()""//## or ##//""Condbroadcast()""//##) between the time a thread locks the mutex and the time it waits on the condition variable (##//""CondWait()""//##), otherwise it seems that it may damage the waiting queue of threads on that condition variable.
**""-""** Thus to avoid that and follow this rule, it is necessary that the mutex remains locked when the condition is signaled.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ4"}}
1) **__Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?__**
**##//While predicate <> True
Condwait(conditionalid, mutexid)
Wend
predicate = False//##**
In all documentations, it is highly advisable to do so, mainly justified to fight against eventual spurious wake-ups.
This is probably true, but it is also advisable to do so to avoid to loose a ##//""CondSignal""//## (or ##//""CondBroadcast""//##) if it is prematurely activated while the receiving thread is not yet waiting on ##//""CondWait""//## (the signal is lost forever):
**""-""** In that case, the receiving thread has even not yet locked the mutex before that ##//""CondSignal""//## (or ##//""CondBroadcast""//##) is activated.
**""-""** So the predicate will already true before the receiving thread reaches the While loop, inducing that ##//""CondWait""//## is downright skipped, so avoiding a definitive blocking phenomenon.
Let two threads (thread #0 in main program, thread #1 in a user procedure, each that prints its number in a loop), having about the same execution time, and each one synchronizing the other in order to well interlace their numbers (by using one mutex, two condition variables and ##//""CondSignal""//##/##//""CondWait""//##):
- Without a While loop on predicate, the program hangs quickly (Ctrl-C to quit):
%%
%%
%%(freebasic)
%%
- With a While loop on predicate around each ##//""CondWait""//##, no blocking phenomenon:
%%
%%
%%{{anchor name="ProPgMtCriticalSectionsFAQ4b"}}
4b. __Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?__
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
%%
%%
%%
%%
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
%%
%%
%%
%%
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ5"}}
1) **__How to implement a user input-line function fully thread-safe?__**
The ##//Input//## keyword may be not thread-safe, when another thread must also access to input/output resource:
**""-""** When executing the ##//Input//## statement, the other running threads must not change the position of the text cursor, which prohibits instructions such as ##//Locate//##, ##//Print//##, ...
**""-""** Moreover, one cannot enclosed the ##//Input//## keyword inside a mutex locking (as we can do it for the ##//Inkey//## keyword), because while the inputting line would be not completed and validated, the other threads that want to also access to input/output would be fully blocked (waiting for mutex unlocking).
Thread-safe input-line function (versus input/output resource):
Input position, prompt message, sleeping time, line-blanking command, mutex pointer can be passed to the following ##//threadInput()//## function that simulates a simplified input function, but thread-safe, by using a looping around the ##//Inkey//## keyword (all input/output keywords must be enclosed inside a mutex locking block, and the cursor position must be restored at each mutex locking block ending):
%%(freebasic)
%%
- From the example 1 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Asynchronous method example using a mutex for all threads", now the running multi-threading code is waiting for the "quit" command in order to exit the program:
%%
%%
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)
%%
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ6"}}
1) **__How to use 'Screenlock' with multi-threading?__**
**""-""** ##//Screenlock...Scrennunlock//## blocks are not compatible with multi-threading (otherwise, the program hangs). This is why a mutex block must be used around each such block to ensure the exclusion.
**""-""** The input keywords (like for keyboard, mouse) cannot be safely run when the screen is locked, therefore a such keyword must be outside of any ##//Screenlock...Screenunlock//## block, so outside any ##//Screenlock...Screenunlock//## block in its own thread, and protected of all ##//Screenlock...Screenunlock//## blocks of other threads by a mutex block. Therefore, ##//Getkey//## and ##//Input//##, the statements that wait for keypress or line input are unusable, but ##//Inkey//## that does not wait can work.
By applying some rules scrupulously, one can use ##//Screenlock//##/##//Screenunlock//## inside the threads.
Principle of coding for all threads including the main code (main thread):
- For example, it is mandatory to use one ##//Mutexlock...Mutexunlock//## block around each ##//Screenlock...Screenunlock//## block, and one other around the ##//Inkey//## instruction which itself must always be outside of any ##//Screenlock...Screenunlock//## bloc:
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no screen locking is used.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ7"}}
1) **__How to use 'video paging (double buffering or page flipping)' with multi-threading?__**
Instead of "screen locking" (see the above paragraph), "video paging (double buffering or page flipping)" can more simply be used with multi-threading, but be careful that many states in the gfxlib2 are thread-dependent like ##//Screenset//## (and also ##//View//## settings, graphic cursor position, graphic colors, ...).
Therefore, the setting for the working page and the visible page must always be controlled in each thread code which want to work with a multi-video page configuration.
- Example for a double buffering method (at each step, each thread needs to update the working page and copy it to the visible page, from within an exclusion mutex code block):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-1.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used.
- Example for a two page flipping method (at each step, each thread needs to update and flip, from within the same exclusion mutex code block, the two screen pages):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-2.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no two page flipping is used.
**Note:** In these two examples, an exclusion mutex code block is mandatory in the two threads, not only because of using console statements + ##//Inkey//##, but around also the graphics statements + ##//Screencopy//## only because of using double buffering method (without anti-flickering process, the graphics statements could be outside the exclusion mutex code block).
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ8"}}
1) **__How to use the FB runtime library for multi-threaded applications (gfxlib2) with multi-threading?__**
The source code of gfxlib2 uses TLS (Thread Local Storage) to store many states, so many things are thread-specific.
Since gfxlib2 is thread-safe, mutex exclusion between threads is not necessary for the graphics statements themselves (including ##//Draw String//##).
In contrast, console statements such as ##//Locate//##, ##//Print//##, ... are not thread-safe as previously mentioned (for example, text cursor position is common to all threads).
- Simple example showing that graphic states (such as graphic cursor position, graphic colors) are thread-dependent:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-1.bas"}}%%(freebasic)
- Example showing that graphics statements (such as Line and Draw String and Screencopy) in a thread can compete with console statements (such as Inkey) in another thread, without using any exclusion (by mutex):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-2.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used.
- From the above example, if the date displaying and the time displaying are now two separate threads, an exclusion mutex code block between these two threads is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two threads:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-3.bas"}}%%(freebasic)
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used, or if no mutex is used.
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ9"}}
1) **__How to use console statements and keyboard inputs with multi-threading?__**
Console statements (such as ##//Locate//##, ##//Print//##, ##//Color//##, ...), as well as ##//Locate//## and ##//Print//## on Graphics window (but not ##//Color//## on Graphics Window), and keyboard inputs (such as ##//Inkey//##, ##//Getkey//##, ##//Input//##, ...) are not thread-safe:
**""-""** Thus when they are used in competing sections of different threads, mutual exclusion is mandatory by means of mutex locking blocks in which in addition code can restore states (such as text cursor position, console color, ...) at end of the block (after its own usage), as they were before (at begin of the block).
**""-""** But the ##//Getkey//## or ##//Input//## keyword cannot be enclosed inside a mutex locking block (as it can be do with the ##//Inkey//## keyword), because as long as the keyboard input is not completed, the other threads in compete would be fully blocked (waiting for the mutex unlocking).
- Example showing that the keywords ##//Locate//## and ##//Print//## are not thread-safe both when applied on a console window or when applied on a graphics window (the text cursor states being not thread dependent in the two cases):
%%(freebasic)
%%Note: One can see that each thread does not write on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.

- From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring cursor states before/after its own cursor moving:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-1.bas"}}%%(freebasic)
%%Note: One can see that each thread writes now on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.

- Example showing that the ##//Color//## keyword is not thread-safe when applied on a console window, but is thread-safe when applied on a graphics window (the color states being thread dependent in that case):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-2.bas"}}%%(freebasic)
%%Note: One can see that the foreground/background colors are not specific to the thread number (id between 1 and 9) on the console window, but this works great on the graphics window.

- From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring color states before/after its own color values usage:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-3.bas"}}%%(freebasic)
%%Note: One can see that the foreground/background colors are now specific to the thread number (id between 1 and 9) on the console window (obviously this always works on the graphics window).

Therefore, for using Getkey or Input in competing sections of threads:
**""-""** Only a single thread (for example, the main thread) can uses ##//Getkey//## or ##//Input//## in addition to console statements (such as ##//Locate//##, ##//Print//##, ##//Color//##, ...) and also ##//Inkey//##, in its competing sections.
**""-""** The other threads must not to use in their competing sections any console statement neither any keyboard input keyword, but can use by cons graphics statements (such as ##//Pset//##, ##//Line//##, ##//Circle//##, ##//Draw String//##, graphic ##//Color//##, ...) which are themselves thread-safe (they can interlace graphically with the main thread without any problem).
**""-""** ##//Input//## and ##//Getkey//## also exclude the screen locking usage in competing sections of threads (double buffering is recommended as anti-flickering method).
- Example showing that graphics statements (such as ##//Line//## and ##//Draw String//## and ##//Screencopy//##) in a thread (user thread here) can compete with console statements (such as ##//Locate//## and ##//Print//## and ##//Input//##) in another thread (main thread here), without using any exclusion (by mutex):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-4.bas"}}%%(freebasic)
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).

- From the above example, if the date displaying and the time displaying are now two separate user threads, an exclusion mutex code block between these two threads only is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two user threads only:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-5.bas"}}%%(freebasic)
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).

@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ10"}}
1) **__Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?__**
A simple 'threadUDT' base Class can be defined as follows:
**""-""** with a private 'Any Ptr' non-static member field for each handle,
**""-""** with a private 'Any Ptr' static member field for one shared mutex,
**""-""** with a private 'Any Ptr' static member field for one shared conditional variable,
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for all 'thread...()', and static procedures for all 'mutex...()' and all 'cond...()'),
**""-""** with an abstract private 'Sub()' thread to be overridden by another 'Sub()' from inside the user derived Type (therefore its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).
- From the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Synchronous method example using a condwait then a condbroadcast (and a mutex) for all threads", now the user implementation is modified to be compatible with the base Class 'threadUDT':
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq10-1.bas"}}%%(freebasic)
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----


Revision [23486]

Edited on 2019-09-17 10:30:11 by fxm [formatting]
Additions:
' ( atomic_mutex_unlock(mut) ) ------. | '------- | --------- bool#1 = true
' ( atomic_mutex_re-lock(mut) ) <--- | ----| .------- | --------> While bool#2 <> true
' Wend | | | | .-------- ( atomic_mutex_unlock(mut) )
' Do_something_with_exclusion | .--- | --- | -------' |---- | ------> ( atomic_mutex_re-lock(mut) )
' ( atomic_mutex_unlock(mutexID) ) -------> to MUTEXLOCK(mutexID) or ( atomic_mutex_re-lock(mutexID) )
' ( atomic_mutex_re-lock(mutexID) ) <------ from ( atomic_mutex_unlock(mutexID) ) or MUTEXUNLOCK(mutexID)
Deletions:
' ( atomic_mutex_unlock(mut) ) --------. | '------- | --------- bool#1 = true
' ( atomic_mutex_re-lock(mut) ) <----- | ----| .------- | --------> While bool#2 <> true
' Wend | | | | .------ ( atomic_mutex_unlock(mut) )
' Do_something_with_exclusion | .--- | --- | -------' |---- | ----> ( atomic_mutex_re-lock(mut) )
' ( atomic_mutex_unlock(mutexID) ) ---------> to MUTEXLOCK(mutexID) or ( atomic_mutex_re-lock(mutexID) )
' ( atomic_mutex_re-lock(mutexID) ) <-------- from ( atomic_mutex_unlock(mutexID) ) or MUTEXUNLOCK(mutexID)


Revision [23483]

Edited on 2019-09-17 02:27:36 by fxm [formatting]
Additions:
Locate This.number, 30 + This.number, 0
UDT.threadPriorityNumber = (UDT.threadPriorityNumber + 1) Mod (UDT.numberMax + 1)
UDT.threadPriorityNumber = (UDT.threadPriorityNumber + 1) Mod (UDT.numberMax + 1)
Deletions:
Locate This.number, 30+This.number, 0
UDT.threadPriorityNumber = (UDT.threadPriorityNumber + 1) Mod (UDT.numberMax+1)
UDT.threadPriorityNumber = (UDT.threadPriorityNumber + 1) Mod (UDT.numberMax+1)


Revision [23481]

Edited on 2019-09-17 02:10:41 by fxm [formatting]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?"}}**
1) **__Can all tools to handle multi-threading be encapsulated in a base Class (that the user extends with a derived Type for his own implementing)?__**
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can all tools to handle multi-threading be encapsulated in a base Class that the user extends with a derived Type for his own implementing?"}}**
1) **__Can all tools to handle multi-threading be encapsulated in a base Class that the user extends with a derived Type for his own implementing?__**


Revision [23480]

Edited on 2019-09-16 15:50:53 by fxm [added question]
Additions:
**""-""** with an abstract private 'Sub()' thread to be overridden by another 'Sub()' from inside the user derived Type (therefore its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).
Deletions:
**""-""** with an abstract private thread 'Sub()' to be overridden by another 'Sub()' from inside the user derived Type (therefore its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).


Revision [23479]

Edited on 2019-09-16 15:24:20 by fxm [added question]
Additions:
**""-""** with an abstract private thread 'Sub()' to be overridden by another 'Sub()' from inside the user derived Type (therefore its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).
Deletions:
**""-""** an abstract private thread 'Sub()' to be overridden by another 'Sub()' from inside the user derived Type (so that its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).


Revision [23478]

Edited on 2019-09-16 15:20:38 by fxm [added question]
Additions:
A simple 'threadUDT' base Class can be defined as follows:
**""-""** with a private 'Any Ptr' static member field for one shared mutex,
**""-""** with a private 'Any Ptr' static member field for one shared conditional variable,
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for all 'thread...()', and static procedures for all 'mutex...()' and all 'cond...()'),
**""-""** an abstract private thread 'Sub()' to be overridden by another 'Sub()' from inside the user derived Type (so that its static address is available in the virtual table of the object, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).
Deletions:
A simple base Class 'threadUDT' can be defined as follows:
**""-""** with a private 'Any Ptr' static member field for one mutex,
**""-""** with a private 'Any Ptr' static member field for one conditional variable,
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for 'create...', and static procedures for 'mutex...' and 'cond...'),
**""-""** an abstract private thread 'Sub()' to be overridden by another 'Sub()' from inside the user derived Type (so that its static 'Sub()' address is available in the virtual table, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).


Revision [23477]

Edited on 2019-09-16 14:50:46 by fxm [added question]
Additions:
A simple base Class 'threadUDT' can be defined as follows:
**""-""** with a private 'Any Ptr' non-static member field for each handle,
**""-""** with a private 'Any Ptr' static member field for one mutex,
**""-""** with a private 'Any Ptr' static member field for one conditional variable,
**""-""** with its own public member procedures 'Sub()' calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for 'create...', and static procedures for 'mutex...' and 'cond...'),
**""-""** an abstract private thread 'Sub()' to be overridden by another 'Sub()' from inside the user derived Type (so that its static 'Sub()' address is available in the virtual table, and the hidden 'This' parameter passed by reference is compatible with the 'Any Ptr' parameter to be passed to the thread).
Deletions:
A base Class 'threadUDT' can be defined as follows:
**""-""** with a private 'Any Ptr' member field for the handle,
**""-""** with a private 'Any Ptr' static member field for a mutex,
**""-""** with a private 'Any Ptr' static member field for a conditional variable,
**""-""** with its own public member procedures calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for 'create...', and static procedures for 'mutex...' and 'cond...'),
**""-""** an abstract private thread 'Sub()' to be overridden by another from inside the user derived Type (so a static 'Sub' address is available in the virtual table, and a hidden parameter 'This' is passed by reference being compatible with the expected 'Any Ptr').


Revision [23476]

Edited on 2019-09-16 11:25:29 by fxm [added question]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can all tools to handle multi-threading be encapsulated in a base Class that the user extends with a derived Type for his own implementing?"}}**
1) **__Can all tools to handle multi-threading be encapsulated in a base Class that the user extends with a derived Type for his own implementing?__**
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can tools to handle multi-threading be encapsulated in a base Class that the user extends with a derived Type for his own implementing?"}}**
1) **__Can tools to handle multi-threading be encapsulated in a base Class that the user extends with a derived Type for his own implementing?__**


Revision [23475]

Edited on 2019-09-16 11:22:06 by fxm [added question]
Additions:
The "**Critical Sections**" related questions.
Deletions:
The "**Critical Sections**" related questions".


Revision [23474]

Edited on 2019-09-16 10:18:50 by fxm [added question]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can tools to handle multi-threading be encapsulated in a base Class that the user extends with a derived Type for his own implementing?"}}**
1) **__Can tools to handle multi-threading be encapsulated in a base Class that the user extends with a derived Type for his own implementing?__**
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can tools to handle multi-threading (with critical sections) be encapsulated in a base Class that the user extends with a derived Type for his own implementing?"}}**
1) **__Can tools to handle multi-threading (with critical sections) be encapsulated in a base Class that the user extends with a derived Type for his own implementing?__**


Revision [23473]

Edited on 2019-09-16 09:31:41 by fxm [added question]
Additions:
4b. __Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?__
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.
{{anchor name="ProPgMtCriticalSectionsFAQ5"}}
Deletions:
4b. __Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?__
##//(another question induced by the previous one)//##
**""-""** The recommended structure is as follows:
%%
%%
%%
%%
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
%%
%%
%%
%%
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
**=>** ""'CondWait'"" is useful to optimize the execution time.
{{anchor name="ProPgMtCriticalSectionsFAQ5"}}


Revision [23472]

Edited on 2019-09-16 09:22:34 by fxm [added question]
Additions:
**""-""** an abstract private thread 'Sub()' to be overridden by another from inside the user derived Type (so a static 'Sub' address is available in the virtual table, and a hidden parameter 'This' is passed by reference being compatible with the expected 'Any Ptr').
Deletions:
**""-""** an abstract thread 'Sub()' to be overridden by another from inside the user derived Type (so a static 'Sub' address is available in the virtual table, and a hidden parameter 'This' is passed by reference being compatible with the expected 'Any Ptr').


Revision [23471]

Edited on 2019-09-16 08:55:23 by fxm [added question]
Additions:
**""-""** with its own public member procedures calling the corresponding built-in procedures for multi-threading (with same procedure names), including also value integrity tests on the 3 above pointers (non-static procedures for 'create...', and static procedures for 'mutex...' and 'cond...'),
Deletions:
**""-""** with its own public member procedures calling the corresponding built-in procedures for multi-threading (with similar procedure names), including also value integrity tests on the 3 above pointer (non-static procedures for 'create...' and static procedures for 'mutex...' and 'cond...'),


Revision [23470]

Edited on 2019-09-16 08:11:26 by fxm [added question]
Additions:
%%(freebasic)
Deletions:
%%(freebasic)


Revision [23469]

Edited on 2019-09-16 07:57:30 by fxm [added question]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can tools to handle multi-threading (with critical sections) be encapsulated in a base Class that the user extends with a derived Type for his own implementing?"}}**
1) **__Can tools to handle multi-threading (with critical sections) be encapsulated in a base Class that the user extends with a derived Type for his own implementing?__**
A base Class 'threadUDT' can be defined as follows:
**""-""** with a private 'Any Ptr' member field for the handle,
**""-""** with a private 'Any Ptr' static member field for a mutex,
**""-""** with a private 'Any Ptr' static member field for a conditional variable,
**""-""** with its own public member procedures calling the corresponding built-in procedures for multi-threading (with similar procedure names), including also value integrity tests on the 3 above pointer (non-static procedures for 'create...' and static procedures for 'mutex...' and 'cond...'),
**""-""** an abstract thread 'Sub()' to be overridden by another from inside the user derived Type (so a static 'Sub' address is available in the virtual table, and a hidden parameter 'This' is passed by reference being compatible with the expected 'Any Ptr').
%%(freebasic)
#include once "fbthread.bi"
Type threadUDT Extends Object
Public:
Declare Sub threadCreate ()
Declare Sub threadWait ()
Declare Sub threadDetach ()
Declare Static Sub mutexCreate ()
Declare Static Sub mutexLock ()
Declare Static Sub mutexUnlock ()
Declare Static Sub mutexDestroy ()
Declare Static Sub condCreate ()
Declare Static Sub condWait ()
Declare Static Sub condSignal ()
Declare Static Sub condBroadcast ()
Declare Static Sub condDestroy ()
Declare Abstract Sub thread ()
Private:
Dim As Any Ptr pThread
Static As Any Ptr pMutex
Static As Any Ptr pCond
Dim As Any Ptr threadUDT.pMutex
Dim As Any Ptr threadUDT.pCond
Sub threadUDT.threadCreate ()
If This.pThread = 0 Then
This.pThread = .Threadcreate(Cast(Any Ptr Ptr Ptr, @This)[0][0], @This)
Sub threadUDT.threadWait ()
If This.pThread > 0 Then
.Threadwait(This.pThread)
This.pThread = 0
Sub threadUDT.threadDetach ()
If This.pThread > 0 Then
.Threaddetach(This.pThread)
This.pThread = 0

Sub threadUDT.mutexCreate ()
If threadUDT.pMutex = 0 Then
threadUDT.pMutex = .Mutexcreate

Sub threadUDT.mutexLock ()
If threadUDT.pMutex > 0 Then
.Mutexlock(threadUDT.pMutex)
Sub threadUDT.mutexUnlock ()
If threadUDT.pMutex > 0 Then
.Mutexunlock(threadUDT.pMutex)
Sub threadUDT.mutexDestroy ()
If threadUDT.pMutex > 0 Then
.Mutexdestroy(threadUDT.pMutex)
threadUDT.pMutex = 0
Sub threadUDT.condCreate ()
If threadUDT.pCond = 0 Then
threadUDT.pCond = .Condcreate
Sub threadUDT.condWait ()
If threadUDT.pCond > 0 And threadUDT.pMutex > 0 Then
.Condwait(threadUDT.pCond, threadUDT.pMutex)
Sub threadUDT.condSignal ()
If threadUDT.pCond > 0 And threadUDT.pMutex > 0 Then
.Condsignal(threadUDT.pCond)
Sub threadUDT.condBroadcast ()
If threadUDT.pCond > 0 And threadUDT.pMutex > 0 Then
.Condbroadcast(threadUDT.pCond)
Sub threadUDT.condDestroy ()
If threadUDT.pCond > 0 Then
.Conddestroy(threadUDT.pCond)
threadUDT.pCond = 0
%%
- From the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Synchronous method example using a condwait then a condbroadcast (and a mutex) for all threads", now the user implementation is modified to be compatible with the base Class 'threadUDT':
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq10-1.bas"}}%%(freebasic)
#include once "fbthread.bi"
Type threadUDT Extends Object
Public:
Declare Sub threadCreate ()
Declare Sub threadWait ()
Declare Sub threadDetach ()
Declare Static Sub mutexCreate ()
Declare Static Sub mutexLock ()
Declare Static Sub mutexUnlock ()
Declare Static Sub mutexDestroy ()
Declare Static Sub condCreate ()
Declare Static Sub condWait ()
Declare Static Sub condSignal ()
Declare Static Sub condBroadcast ()
Declare Static Sub condDestroy ()
Declare Abstract Sub thread ()
Private:
Dim As Any Ptr pThread
Static As Any Ptr pMutex
Static As Any Ptr pCond
Dim As Any Ptr threadUDT.pMutex
Dim As Any Ptr threadUDT.pCond
Sub threadUDT.threadCreate ()
If This.pThread = 0 Then
This.pThread = .Threadcreate(Cast(Any Ptr Ptr Ptr, @This)[0][0], @This)
Sub threadUDT.threadWait ()
If This.pThread > 0 Then
.Threadwait(This.pThread)
This.pThread = 0
Sub threadUDT.threadDetach ()
If This.pThread > 0 Then
.Threaddetach(This.pThread)
This.pThread = 0

Sub threadUDT.mutexCreate ()
If threadUDT.pMutex = 0 Then
threadUDT.pMutex = .Mutexcreate

Sub threadUDT.mutexLock ()
If threadUDT.pMutex > 0 Then
.Mutexlock(threadUDT.pMutex)
Sub threadUDT.mutexUnlock ()
If threadUDT.pMutex > 0 Then
.Mutexunlock(threadUDT.pMutex)
Sub threadUDT.mutexDestroy ()
If threadUDT.pMutex > 0 Then
.Mutexdestroy(threadUDT.pMutex)
threadUDT.pMutex = 0
Sub threadUDT.condCreate ()
If threadUDT.pCond = 0 Then
threadUDT.pCond = .Condcreate
Sub threadUDT.condWait ()
If threadUDT.pCond > 0 And threadUDT.pMutex > 0 Then
.Condwait(threadUDT.pCond, threadUDT.pMutex)
Sub threadUDT.condSignal ()
If threadUDT.pCond > 0 And threadUDT.pMutex > 0 Then
.Condsignal(threadUDT.pCond)
Sub threadUDT.condBroadcast ()
If threadUDT.pCond > 0 And threadUDT.pMutex > 0 Then
.Condbroadcast(threadUDT.pCond)
Sub threadUDT.condDestroy ()
If threadUDT.pCond > 0 Then
.Conddestroy(threadUDT.pCond)
threadUDT.pCond = 0
Type UDT Extends threadUDT
Declare Sub counter ()
Declare Sub thread ()
Dim As ULongInt count
Static As Integer threadPriorityNumber
Dim As Integer UDT.threadPriorityNumber
Sub UDT.counter ()
Locate This.number, This.number, 0
Sleep 5, 1
This.count += 1
Print This.count;
Locate This.number, 30+This.number, 0
Sub UDT.Thread ()
This.mutexLock()
While UDT.threadPriorityNumber <> This.number '' synchronous condwait for expected condition
This.condWait()
This.counter()
myquit = UDT.quit
UDT.threadPriorityNumber = (UDT.threadPriorityNumber + 1) Mod (UDT.numberMax+1)
This.condBroadcast()
This.mutexUnlock()
Sleep This.tempo, 1
Loop Until myquit = 1
UDT.mutexCreate()
UDT.condCreate()
u(I).threadCreate()
UDT.mutexLock()
While UDT.threadPriorityNumber <> u(0).number
UDT.condWait()
If s <> "" Then
UDT.quit = 1
UDT.threadPriorityNumber = (UDT.threadPriorityNumber + 1) Mod (UDT.numberMax+1)
UDT.condBroadcast()
UDT.mutexUnlock()
Sleep u(0).tempo, 1
Loop Until s <> ""
u(I).threadWait()
UDT.mutexDestroy()
UDT.condDestroy()
Dim As ULongInt c
Locate UDT.numberMax+2, 1
Print CULngInt(c / t) & " increments per second"
%%
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can tools to handle multi-threading (with critical sections) be encapsulated in a base Class that the user extends with a derived Type for his implementing?"}}**
1) **__Can tools to handle multi-threading (with critical sections) be encapsulated in a base Class that the user extends with a derived Type for his implementing?__**


Revision [23468]

Edited on 2019-09-16 06:46:23 by fxm [added question in progress...]
Additions:
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
Deletions:
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@


Revision [23467]

Edited on 2019-09-16 06:42:53 by fxm [added question in progress...]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ10|10. Can tools to handle multi-threading (with critical sections) be encapsulated in a base Class that the user extends with a derived Type for his implementing?"}}**
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQ10"}}
1) **__Can tools to handle multi-threading (with critical sections) be encapsulated in a base Class that the user extends with a derived Type for his implementing?__**
Deletions:
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@


Revision [23465]

Edited on 2019-09-16 02:10:31 by fxm [formatting]
Additions:
Dim As Integer myquit
myquit = .quit
Loop Until myquit = 1
Deletions:
Dim As Integer quit
quit = .quit
Loop Until quit = 1


Revision [23461]

Edited on 2019-09-15 10:11:04 by fxm [formatting]
Additions:
' Thread#0 XOR + <==> Thread#1
' MutexLock(mut) <-------------------------. .----------> MutexLock(mut)
' ( atomic_mutex_unlock(mut) ) ------. | | Do_something_with_exclusion
' CondWait(cond#1, mut) <----------- | --- | ----------- | ---------- CondSignal(cond#1)
' ( atomic_mutex_re-lock(mut) ) <--- | ----'----. | .----- ( atomic_mutex_unlock(mut) )
' Do_something_with_exclusion | .--- | ------ | --- | ---> CondWait(cond#2, mut)
' CondSignal(cond#2) --------------- | ----' | .---'---- | ---> ( atomic_mutex_re-lock(mut) )
' Do_something_with_exclusion | .--- | ---' | Do_something_with_exclusion
' MutexUnlock(mut) ------------------'-----' '--------------'----- MutexUnlock(mut)
' ..... .....
' ( atomic_mutex_unlock(mut) ) --------. | '------- | --------- bool#1 = true
' ( atomic_mutex_re-lock(mut) ) <----- | ----| .------- | --------> While bool#2 <> true
' Wend | | | | .------ ( atomic_mutex_unlock(mut) )
' Do_something_with_exclusion | .--- | --- | -------' |---- | ----> ( atomic_mutex_re-lock(mut) )
' MUTEXLOCK(mutexID) <------------------------- from ( atomic_mutex_unlock(mutexID) ) or MUTEXUNLOCK(mutexID)
' ( atomic_mutex_unlock(mutexID) ) ---------> to MUTEXLOCK(mutexID) or ( atomic_mutex_re-lock(mutexID) )
' ( atomic_mutex_re-lock(mutexID) ) <-------- from ( atomic_mutex_unlock(mutexID) ) or MUTEXUNLOCK(mutexID)
' MUTEXUNLOCK(mutexID) -----------------------> to MUTEXLOCK(mutexID) or ( atomic_mutex_re-lock(mutexID) )
' MUTEXLOCK(mutexID) <------------------------- from ( atomic_mutex_unlock(mutexID) ) or MUTEXUNLOCK(mutexID)
' MUTEXUNLOCK(mutexID) -----------------------> to MUTEXLOCK(mutexID) or ( atomic_mutex_re-lock(mutexID) )
Deletions:
' Thread#0 XOR + <==> Thread#1
' MutexLock(mut) <-----------------------. .----------> MutexLock(mut)
' (atomic_mutex_unlock(mut)) ------. | | Do_something_with_exclusion
' CondWait(cond#1, mut) <--------- | --- | ----------- | ---------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <--- | ----'----. | .----- (atomic_mutex_unlock(mut))
' Do_something_with_exclusion | .--- | ------ | --- | ---> CondWait(cond#2, mut)
' CondSignal(cond#2) ------------- | ----' | .---'---- | ---> (atomic_mutex_re-lock(mut))
' Do_something_with_exclusion | .--- | ---' | Do_something_with_exclusion
' MutexUnlock(mut) ----------------'-----' '--------------'----- MutexUnlock(mut)
' (atomic_mutex_unlock(mut)) ----------. | '------- | --------- bool#1 = true
' (atomic_mutex_re-lock(mut)) <------- | ----| .------- | --------> While bool#2 <> true
' Wend | | | | .------ (atomic_mutex_unlock(mut))
' Do_something_with_exclusion | .--- | --- | -------' |---- | ----> (atomic_mutex_re-lock(mut))
' MUTEXLOCK(mutexID) <------------------------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' (atomic_mutex_unlock(mutexID)) -----------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' (atomic_mutex_re-lock(mutexID)) <---------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' MUTEXUNLOCK(mutexID) -----------------------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' MUTEXLOCK(mutexID) <------------------------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' MUTEXUNLOCK(mutexID) -----------------------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))


Revision [23459]

Edited on 2019-09-15 08:35:20 by fxm [formatting]
Additions:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' ..... .....
' Thread#0 XOR + <==> Thread#1
Deletions:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' ..... .....
' Thread#0 XOR + <==> Thread#1
' ..... .....


Revision [23458]

Edited on 2019-09-15 08:23:47 by fxm [formatting]
Additions:
' ..... .....
' MutexLock(mut) <-----------------------------. .---------> MutexLock(mut)
' While bool#1 <> true <---------------------- | ---. | Do_something_with_exclusion
' (atomic_mutex_unlock(mut)) ----------. | '------- | --------- bool#1 = true
' CondWait(cond#1, mut) <----------- | --- | ----------- | --------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <------- | ----| .------- | --------> While bool#2 <> true
' Wend | | | | .------ (atomic_mutex_unlock(mut))
' bool#1 = false .------- | --- | ---' .--- | --- | ------> CondWait(cond#2, mut)
' Do_something_with_exclusion | .--- | --- | -------' |---- | ----> (atomic_mutex_re-lock(mut))
' bool#2 = true ----------------' | |---- | ------------' | Wend
' CondSignal(cond#2) ---------------' | | | bool#2 = false
' Do_something_with_exclusion | | | Do_something_with_exclusion
' MutexUnlock(mut) ----------------------' '-------------------'---- MutexUnlock(mut)
' (atomic_mutex_unlock(mutexID)) -----------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' (atomic_mutex_re-lock(mutexID)) <---------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
Deletions:
' MutexLock(mut) <-------------------------------. .---------> MutexLock(mut)
' While bool#1 <> true <------------------------ | ---. | Do_something_with_exclusion
' (atomic_mutex_unlock(mut)) ----------. | '------- | --------- bool#1 = true
' CondWait(cond#1, mut) <------------- | --- | ----------- | --------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <------- | ----| .------- | --------> While bool#2 <> true
' Wend | | | | .-------- (atomic_mutex_unlock(mut))
' bool#1 = false .------- | --- | ---' .--- | --- | ------> CondWait(cond#2, mut)
' Do_something_with_exclusion | .--- | --- | -------' |---- | ------> (atomic_mutex_re-lock(mut))
' bool#2 = true ------------------' | |---- | ------------' | Wend
' CondSignal(cond#2) -----------------' | | | bool#2 = false
' Do_something_with_exclusion | | | Do_something_with_exclusion
' MutexUnlock(mut) ------------------------' '-------------------'---- MutexUnlock(mut)
' (atomic_mutex_unlock(mutexID)) ---------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' (atomic_mutex_re-lock(mutexID)) <-------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)


Revision [23456]

Edited on 2019-09-15 04:04:32 by fxm [new page created]
Additions:
' ..... .....
' MutexLock(mut) <-----------------------. .----------> MutexLock(mut)
' (atomic_mutex_unlock(mut)) ------. | | Do_something_with_exclusion
' CondWait(cond#1, mut) <--------- | --- | ----------- | ---------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <--- | ----'----. | .----- (atomic_mutex_unlock(mut))
' Do_something_with_exclusion | .--- | ------ | --- | ---> CondWait(cond#2, mut)
' CondSignal(cond#2) ------------- | ----' | .---'---- | ---> (atomic_mutex_re-lock(mut))
' Do_something_with_exclusion | .--- | ---' | Do_something_with_exclusion
' MutexUnlock(mut) ----------------'-----' '--------------'----- MutexUnlock(mut)
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <-------------------------------. .---------> MutexLock(mut)
' While bool#1 <> true <------------------------ | ---. | Do_something_with_exclusion
' (atomic_mutex_unlock(mut)) ----------. | '------- | --------- bool#1 = true
' CondWait(cond#1, mut) <------------- | --- | ----------- | --------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <------- | ----| .------- | --------> While bool#2 <> true
' Wend | | | | .-------- (atomic_mutex_unlock(mut))
' bool#1 = false .------- | --- | ---' .--- | --- | ------> CondWait(cond#2, mut)
' Do_something_with_exclusion | .--- | --- | -------' |---- | ------> (atomic_mutex_re-lock(mut))
' bool#2 = true ------------------' | |---- | ------------' | Wend
' CondSignal(cond#2) -----------------' | | | bool#2 = false
' Do_something_with_exclusion | | | Do_something_with_exclusion
' MutexUnlock(mut) ------------------------' '-------------------'---- MutexUnlock(mut)
' ..... .....
Deletions:
' MutexLock(mut) <-----------------------. .----------> MutexLock(mut)
' (atomic_mutex_unlock(mut)) ------. | | Do_something_with_exclusion
' CondWait(cond#1, mut) <--------- | --- | ------------ | ---------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <--- | ----'----. | .----- (atomic_mutex_unlock(mut))
' Do_something_with_exclusion | | .--- | --- | ---> CondWait(cond#2, mut)
' CondSignal(cond#2) ------------- | -------- | ---' |---- | ---> (atomic_mutex_re-lock(mut))
' Do_something_with_exclusion | .--- | --------' | Do_something_with_exclusion
' MutexUnlock(mut) ----------------'-----' '---------------'----- MutexUnlock(mut)
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <-------------------------------. .---------------------> MutexLock(mut)
' While bool#1 <> true <------------------------ | --- | ---. Do_something_with_exclusion
' (atomic_mutex_unlock(mut)) ----------. | | '----------------- bool#1 = true
' CondWait(cond#1, mut) <------------- | --- | --- | --------------------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <------- | ----| | .----------------> While bool#2 <> true
' Wend | | | | .-------- (atomic_mutex_unlock(mut))
' bool#1 = false .------- | --- | --- | ---' .------- | ------> CondWait(cond#2, mut)
' Do_something_with_exclusion | .--- | --- | --- | -------' .--- | ------> (atomic_mutex_re-lock(mut))
' bool#2 = true ------------------' | |---- | ----'------------' | Wend
' CondSignal(cond#2) -----------------' | | | bool#2 = false
' Do_something_with_exclusion | | | Do_something_with_exclusion
' MutexUnlock(mut) ------------------------' '-----------------------'---- MutexUnlock(mut)
' ..... .....


Revision [23455]

Edited on 2019-09-15 03:50:20 by fxm [new page created]
Additions:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <-----------------------. .----------> MutexLock(mut)
' (atomic_mutex_unlock(mut)) ------. | | Do_something_with_exclusion
' CondWait(cond#1, mut) <--------- | --- | ------------ | ---------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <--- | ----'----. | .----- (atomic_mutex_unlock(mut))
' Do_something_with_exclusion | | .--- | --- | ---> CondWait(cond#2, mut)
' CondSignal(cond#2) ------------- | -------- | ---' |---- | ---> (atomic_mutex_re-lock(mut))
' Do_something_with_exclusion | .--- | --------' | Do_something_with_exclusion
' MutexUnlock(mut) ----------------'-----' '---------------'----- MutexUnlock(mut)
' ..... .....
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <-------------------------------. .---------------------> MutexLock(mut)
' While bool#1 <> true <------------------------ | --- | ---. Do_something_with_exclusion
' (atomic_mutex_unlock(mut)) ----------. | | '----------------- bool#1 = true
' CondWait(cond#1, mut) <------------- | --- | --- | --------------------- CondSignal(cond#1)
' (atomic_mutex_re-lock(mut)) <------- | ----| | .----------------> While bool#2 <> true
' Wend | | | | .-------- (atomic_mutex_unlock(mut))
' bool#1 = false .------- | --- | --- | ---' .------- | ------> CondWait(cond#2, mut)
' Do_something_with_exclusion | .--- | --- | --- | -------' .--- | ------> (atomic_mutex_re-lock(mut))
' bool#2 = true ------------------' | |---- | ----'------------' | Wend
' CondSignal(cond#2) -----------------' | | | bool#2 = false
' Do_something_with_exclusion | | | Do_something_with_exclusion
' MutexUnlock(mut) ------------------------' '-----------------------'---- MutexUnlock(mut)
' ..... .....
Deletions:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <----------------. .--------> MutexLock(mut)
' CondWait(cond#1, mut) <-------- | -------- | ---. Do_something_with_exclusion
' Do_something_with_exclusion <---'----. | '---- CondSignal(cond#1)
' CondSignal(cond#2) ----------------- | --- | -------> CondWait(cond#2, mut)
' Do_something_with_exclusion .--- | ----'--------> Do_something_with_exclusion
' MutexUnlock(mut) ---------------' '--------------- MutexUnlock(mut)
' ..... .....
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <---------------. .-----------> MutexLock(mut)
' While bool#1 <> true <-------- | ---------------- | ------. Do_something_with_exclusion
' CondWait(cond#1, mut) <--- | ---------------- | --. '---- bool#1 = true
' Wend <-------------------------'------------. | '-------- CondSignal(cond#1)
' 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)
' ..... .....


Revision [23454]

Edited on 2019-09-15 02:45:01 by fxm [new page created]
Additions:
' While bool#1 <> true <-------- | ---------------- | ------. Do_something_with_exclusion
' CondWait(cond#1, mut) <--- | ---------------- | --. '---- bool#1 = true
Deletions:
' While bool#1 <> true <-------- | -----------------|-------. Do_something_with_exclusion
' CondWait(cond#1, mut) <--- | -----------------|---. '---- bool#1 = true


Revision [23453]

Edited on 2019-09-15 02:35:46 by fxm [new page created]
Additions:
' Do_something_with_exclusion <---'----. | '---- CondSignal(cond#1)
Deletions:
' Do_something_with_exclusion <---'----. | '---> CondSignal(cond#1)


Revision [23452]

Edited on 2019-09-15 02:06:05 by fxm [new page created]
Additions:
' Thread#0 XOR + <==> Thread#1
' MutexLock(mut) <----------------. .--------> MutexLock(mut)
' CondWait(cond#1, mut) <-------- | -------- | ---. Do_something_with_exclusion
' Do_something_with_exclusion <---'----. | '---> CondSignal(cond#1)
' CondSignal(cond#2) ----------------- | --- | -------> CondWait(cond#2, mut)
' Do_something_with_exclusion .--- | ----'--------> Do_something_with_exclusion
' MutexUnlock(mut) ---------------' '--------------- MutexUnlock(mut)
' ..... .....
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <---------------. .-----------> MutexLock(mut)
' While bool#1 <> true <-------- | -----------------|-------. Do_something_with_exclusion
' CondWait(cond#1, mut) <--- | -----------------|---. '---- bool#1 = true
' Wend <-------------------------'------------. | '-------- CondSignal(cond#1)
' 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)
' ..... .....
Deletions:
' Thread#0 XOR + <==> Thread#1
' MutexLock(mut) <----------------. .----> MutexLock(mut)
' Do_something_with_exclusion | | Do_something_with_exclusion
' CondWait(cond#1, mut) <-------- | ------------ | ---- CondSignal(cond#1)
' Do_something_with_exclusion <---'--------. | Do_something_with_exclusion
' CondSignal(cond#2) --------------------- | --- | ---> CondWait(cond#2, mut)
' Do_something_with_exclusion .------- | ----'----> Do_something_with_exclusion
' MutexUnlock(mut) ---------------' '----------- MutexUnlock(mut)
' Thread#0 XOR + <==> Thread#1
' ..... .....
' 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)
' ..... .....


Revision [23451]

Edited on 2019-09-15 01:13:41 by fxm [new page created]
Additions:
' While bool#1 <> true <-------- | ---------------- | ---- bool#1 = true
' CondWait(cond#1, mut) <--- | ---------------- | ---- CondSignal(cond#1)
Deletions:
' While bool#1 <> true <-------- | -----------------|----- bool#1 = true
' CondWait(cond#1, mut) <--- | -----------------|----- CondSignal(cond#1)


Revision [23441]

Edited on 2019-09-14 09:19:40 by fxm [new page created]
Additions:
**=>** ""'CondWait'"" is useful to optimize the execution time.
Deletions:
""'Cond Wait'"" is useful to optimize the execution time.


Revision [23440]

Edited on 2019-09-14 09:09:01 by fxm [new page created]
Additions:
' Principle of mutual exclusion + CONDWAIT in a While loop with predicate check, for a thread sub-section
' Thread Other Thread
' MUTEXLOCK(mutexID) <------------------------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' While booleanT <> True <--------------------- from booleanT = True
' (atomic_mutex_unlock(mutexID)) ---------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' CONDWAIT(conditionalID, mutexID) <------- from CONDSIGNAL(conditionalID)
' (atomic_mutex_re-lock(mutexID)) <-------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' MUTEXUNLOCK(mutexID) -----------------------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' Principle of mutual exclusion + CONDSIGNAL with predicate check, for a thread sub-section
' Thread Other Thread
' MUTEXLOCK(mutexID) <------------------------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' booleanOT = True ---------------------------> to While booleanOT <> True
' CONDSIGNAL(conditionalID) ------------------> to CONDWAIT(conditionalID, mutexID)
' MUTEXUNLOCK(mutexID) -----------------------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' Principle of mutual exclusion + SLEEP in a While loop with predicate check, for a thread sub-section
' Thread Other Thread
' MUTEXLOCK(mutexID) <------------------------- from MUTEXUNLOCK(mutexID)
' While booleanT <> True <--------------------- from booleanT = True
' MUTEXUNLOCK(mutexID) -------------------> to MUTEXLOCK(mutexID)
' MUTEXLOCK(mutexID) <--------------------- from MUTEXUNLOCK(mutexID)
' MUTEXUNLOCK(mutexID) -----------------------> to MUTEXLOCK(mutexID)
' Principle of mutual exclusion + predicate check only, for a thread sub-section
' Thread Other Thread
' MUTEXLOCK(mutexID) <------------------------- from MUTEXUNLOCK(mutexID)
' booleanOT = True ---------------------------> to While booleanOT <> True
' MUTEXUNLOCK(mutexID) -----------------------> to MUTEXLOCK(mutexID)
Deletions:
' Principle of mutual exclusion + CONDWAIT in a While loop with predicate, for a thread sub-section
' Thread Other Thread
' MUTEXLOCK(mutexID) <-------------------------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' While booleanT <> True <---------------------- from booleanT = True
' (atomic_mutex_unlock(mutexID)) ----------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' CONDWAIT(conditionalID, mutexID) <-------- from CONDSIGNAL(conditionalID)
' (atomic_mutex_re-lock(mutexID)) <--------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' MUTEXUNLOCK(mutexID) ------------------------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' Principle of mutual exclusion + SLEEP in a While loop with predicate, for a thread sub-section
' Thread Other Thread
' MUTEXLOCK(mutexID) <-------------------------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' While booleanT <> True <---------------------- from booleanT = True
' MUTEXUNLOCK(mutexID) --------------------> to MUTEXLOCK(mutexID)
' MUTEXLOCK(mutexID) <---------------------- from MUTEXUNLOCK(mutexID)
' MUTEXUNLOCK(mutexID) ------------------------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID)) %%


Revision [23439]

Edited on 2019-09-14 07:53:13 by fxm [new page created]
Additions:
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?"}}
4b. __Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by other thread?__
##//(another question induced by the previous one)//##
Deletions:
##//another question induced by the previous one://##
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by another thread?"}}
**//Another question induced by the previous one://**
4b. __Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by another thread?__


Revision [23438]

Edited on 2019-09-14 07:44:09 by fxm [new page created]
Additions:
##//another question induced by the previous one://##
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by another thread?"}}
**//Another question induced by the previous one://**
4b. __Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when there is already a 'While' loop for checking a Boolean predicate set by another thread?__
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release another thread):
Deletions:
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?""}}
##(another question induced by the previous one)##
**Another question induced by the previous one:**
4b. __Is ""'Condwait'"" (and ""'Condsignal'"" or ""'Condbroadcast'"") still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?__
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release other threads):


Revision [23437]

Edited on 2019-09-14 07:33:43 by fxm [new page created]
Additions:
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal' or 'Condbroadcast') still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?""}}
##(another question induced by the previous one)##
4b. __Is ""'Condwait'"" (and ""'Condsignal'"" or ""'Condbroadcast'"") still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?__
Deletions:
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal'/'Condbroadcast') still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?""}}
4b. __Is ""'Condwait'"" (and ""'Condsignal'""/""'Condbroadcast'"") still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?__


Revision [23436]

Edited on 2019-09-14 07:26:27 by fxm [new page created]
Additions:
4b. __Is ""'Condwait'"" (and ""'Condsignal'""/""'Condbroadcast'"") still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?__
Deletions:
__Is ""'Condwait'"" (and ""'Condsignal'""/""'Condbroadcast'"") still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?__


Revision [23435]

Edited on 2019-09-14 07:23:36 by fxm [new page created]
Additions:
{{anchor name="ProPgMtCriticalSectionsFAQ4b|4b. Is 'Condwait' (and 'Condsignal'/'Condbroadcast') still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?""}}
%%{{anchor name="ProPgMtCriticalSectionsFAQ4b"}}


Revision [23434]

Edited on 2019-09-14 06:40:49 by fxm [new page created]
Additions:
**Another question induced by the previous one:**
__Is ""'Condwait'"" (and ""'Condsignal'""/""'Condbroadcast'"") still useful when a 'While' loop for checking a Boolean predicate (set by another thread) already exists?__
**""-""** The recommended structure is as follows:
%%
' Principle of mutual exclusion + CONDWAIT in a While loop with predicate, for a thread sub-section
' (connecting lines join the sender(s) and receiver( with predicateeach action occurring during the sequence)
' Thread Other Thread
' MUTEXLOCK(mutexID) <-------------------------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' .......
' While booleanT <> True <---------------------- from booleanT = True
' (atomic_mutex_unlock(mutexID)) ----------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
' CONDWAIT(conditionalID, mutexID) <-------- from CONDSIGNAL(conditionalID)
' (atomic_mutex_re-lock(mutexID)) <--------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' Wend
' booleanT = False
' .......
' MUTEXUNLOCK(mutexID) ------------------------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID))
%%
**""-""** If ""'CondWait'"" is not used, it is mandatory to put instead a 'Sleep' instruction in the 'While' loop on the Boolean flag, in order to release time-slice when looping (in addition, this 'Sleep' must be put inside a ['Mutexunlock'...'Mutexlock'] block to release other threads):
%%
' Principle of mutual exclusion + SLEEP in a While loop with predicate, for a thread sub-section
' Thread Other Thread
' MUTEXLOCK(mutexID) <-------------------------- from (atomic_mutex_unlock(mutexID)) or MUTEXUNLOCK(mutexID)
' .......
' While booleanT <> True <---------------------- from booleanT = True
' MUTEXUNLOCK(mutexID) --------------------> to MUTEXLOCK(mutexID)
' SLEEP(tempo)
' MUTEXLOCK(mutexID) <---------------------- from MUTEXUNLOCK(mutexID)
' Wend
' booleanT = False
' .......
' MUTEXUNLOCK(mutexID) ------------------------> to MUTEXLOCK(mutexID) or (atomic_mutex_re-lock(mutexID)) %%
During ""'CondWait'"", the thread execution is suspended and does not consume any CPU time until the condition variable is signaled.
But if Sleep is put instead, the waiting time is predetermined and not self adaptive like that of ""'CondWait'"".
""'Cond Wait'"" is useful to optimize the execution time.


Revision [23433]

Edited on 2019-09-14 04:28:15 by fxm [new page created]
Additions:
**""-""** in 32-bit => Many erroneous points not on the circle but anywhere in the square containing the circle. If you uncomment the four lines 37/39/58/60 to activate the mutex, then all the got points are now on the circle only.
**""-""** in 64-bit => All points are valid, on the circle only, even if the mutex is not activated.
' Thread#0 XOR + <==> Thread#1
' 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)
' ..... .....
Deletions:
**""-""** in 32-bit => many erroneous points not on the circle but anywhere in the square containing the circle (if you uncomment the four lines 37/39/58/60 to activate the mutex, then all the got points are now on the circle only),
**""-""** in 64-bit => all points are valid, on the circle only, even if the mutex is not activated.
' Thread#0 XOR + <==> Thread#1
' 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)


Revision [23432]

Edited on 2019-09-14 04:14:59 by fxm [new page created]
Additions:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) <----------------. .----> MutexLock(mut)
' Do_something_with_exclusion | | Do_something_with_exclusion
' CondWait(cond#1, mut) <-------- | ------------ | ---- CondSignal(cond#1)
' Do_something_with_exclusion <---'--------. | Do_something_with_exclusion
' CondSignal(cond#2) --------------------- | --- | ---> CondWait(cond#2, mut)
' Do_something_with_exclusion .------- | ----'----> Do_something_with_exclusion
' MutexUnlock(mut) ---------------' '----------- MutexUnlock(mut)
' ..... .....
' (connecting lines join the sender(s) and receiver(s) impacted by each action occurring during the sequence)
' Thread#0 XOR + <==> Thread#1
' ..... .....
' 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)
' ..... .....
' (connecting lines join the sender(s) and receiver(s) impacted by each action occurring during the sequence)
Deletions:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) MutexLock(mut)
' Do_something_with_exclusion Do_something_with_exclusion
' CondWait(cond#1, mut) <----------------------- CondSignal(cond#1)
' Do_something_with_exclusion <---------. Do_something_with_exclusion
' CondSignal(cond#2) ------------------ | -----> CondWait(cond#2, mut)
' Do_something_with_exclusion .---- | -----> Do_something_with_exclusion
' MutexUnlock(mut) ---------------' '------- MutexUnlock(mut)
' ..... .....
' Thread#0 XOR + <==> Thread#1
' ..... .....
' 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)
' ..... .....


Revision [23430]

Edited on 2019-09-14 00:41:14 by fxm [new page created]
Additions:
- Without a While loop on predicate, the program hangs quickly (Ctrl-C to quit):
- With a While loop on predicate around each ##//""CondWait""//##, no blocking phenomenon:
- From the example 1 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Asynchronous method example using a mutex for all threads", now the running multi-threading code is waiting for the "quit" command in order to exit the program:
- For example, it is mandatory to use one ##//Mutexlock...Mutexunlock//## block around each ##//Screenlock...Screenunlock//## block, and one other around the ##//Inkey//## instruction which itself must always be outside of any ##//Screenlock...Screenunlock//## bloc:
- Example for a double buffering method (at each step, each thread needs to update the working page and copy it to the visible page, from within an exclusion mutex code block):
- Example for a two page flipping method (at each step, each thread needs to update and flip, from within the same exclusion mutex code block, the two screen pages):
- Simple example showing that graphic states (such as graphic cursor position, graphic colors) are thread-dependent:
- Example showing that graphics statements (such as Line and Draw String and Screencopy) in a thread can compete with console statements (such as Inkey) in another thread, without using any exclusion (by mutex):
- From the above example, if the date displaying and the time displaying are now two separate threads, an exclusion mutex code block between these two threads is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two threads:
- Example showing that the keywords ##//Locate//## and ##//Print//## are not thread-safe both when applied on a console window or when applied on a graphics window (the text cursor states being not thread dependent in the two cases):
- From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring cursor states before/after its own cursor moving:
- Example showing that the ##//Color//## keyword is not thread-safe when applied on a console window, but is thread-safe when applied on a graphics window (the color states being thread dependent in that case):
- From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring color states before/after its own color values usage:
- Example showing that graphics statements (such as ##//Line//## and ##//Draw String//## and ##//Screencopy//##) in a thread (user thread here) can compete with console statements (such as ##//Locate//## and ##//Print//## and ##//Input//##) in another thread (main thread here), without using any exclusion (by mutex):
- From the above example, if the date displaying and the time displaying are now two separate user threads, an exclusion mutex code block between these two threads only is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two user threads only:
Deletions:
**""-""** Without a While loop on predicate, the program hangs quickly (Ctrl-C to quit):
**""-""** With a While loop on predicate around each ##//""CondWait""//##, no blocking phenomenon:
From the example 1 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Asynchronous method example using a mutex for all threads", now the running multi-threading code is waiting for the "quit" command in order to exit the program:
For example, it is mandatory to use one ##//Mutexlock...Mutexunlock//## block around each ##//Screenlock...Screenunlock//## block, and one other around the ##//Inkey//## instruction which itself must always be outside of any ##//Screenlock...Screenunlock//## bloc:
**""-""** Example for a double buffering method (at each step, each thread needs to update the working page and copy it to the visible page, from within an exclusion mutex code block):
**""-""** Example for a two page flipping method (at each step, each thread needs to update and flip, from within the same exclusion mutex code block, the two screen pages):
**""-""** Simple example showing that graphic states (such as graphic cursor position, graphic colors) are thread-dependent:
**""-""** Example showing that graphics statements (such as Line and Draw String and Screencopy) in a thread can compete with console statements (such as Inkey) in another thread, without using any exclusion (by mutex):
**""-""** From the above example, if the date displaying and the time displaying are now two separate threads, an exclusion mutex code block between these two threads is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two threads:
**""-""** Example showing that the keywords ##//Locate//## and ##//Print//## are not thread-safe both when applied on a console window or when applied on a graphics window (the text cursor states being not thread dependent in the two cases):
**""-""** From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring cursor states before/after its own cursor moving:
**""-""** Example showing that the ##//Color//## keyword is not thread-safe when applied on a console window, but is thread-safe when applied on a graphics window (the color states being thread dependent in that case):
**""-""** From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring color states before/after its own color values usage:
**""-""** Example showing that graphics statements (such as ##//Line//## and ##//Draw String//## and ##//Screencopy//##) in a thread (user thread here) can compete with console statements (such as ##//Locate//## and ##//Print//## and ##//Input//##) in another thread (main thread here), without using any exclusion (by mutex):
**""-""** From the above example, if the date displaying and the time displaying are now two separate user threads, an exclusion mutex code block between these two threads only is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two user threads only:


Revision [23423]

Edited on 2019-09-12 13:26:27 by fxm [new page created]
Additions:
**===@@'Critical sections' related questions@@===**
Deletions:
**==@@'Critical sections' related questions@@==**


Revision [23422]

Edited on 2019-09-12 13:22:57 by fxm [new page created]
Additions:
**==@@'Critical sections' related questions@@==**
Deletions:
==@@'Critical sections' related questions@@==


Revision [23421]

Edited on 2019-09-12 13:00:44 by fxm [new page created]
Additions:
Thread-safe input-line function (versus input/output resource):
Input position, prompt message, sleeping time, line-blanking command, mutex pointer can be passed to the following ##//threadInput()//## function that simulates a simplified input function, but thread-safe, by using a looping around the ##//Inkey//## keyword (all input/output keywords must be enclosed inside a mutex locking block, and the cursor position must be restored at each mutex locking block ending):
From the example 1 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Asynchronous method example using a mutex for all threads", now the running multi-threading code is waiting for the "quit" command in order to exit the program:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)
{{anchor name="ProPgMtCriticalSectionsFAQ6"}}
Deletions:
- Thread-safe input-line function (versus input/output resource):
Input position, prompt message, sleeping time, line-blanking command, mutex pointer can be passed to the following ##//threadInput()//## function that simulates a simplified input function, but thread-safe, by using a looping around the ##//Inkey//## keyword (all input/output keywords must be enclosed inside a mutex locking block, and the cursor position must be restored at each mutex locking block ending):
%%(freebasic)
%%
From the example 1 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Asynchronous method example using a mutex for all threads", now the running multi-threading code is waiting for the "quit" command in order to exit the program:
%%
%%
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)
%%
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
----
{{anchor name="ProPgMtCriticalSectionsFAQ6"}}


Revision [23420]

Edited on 2019-09-12 12:50:36 by fxm [new page created]
Additions:
1) **__When is it not mandatory to protect by a mutex one shared variable between several threads?__**
1) **__What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__**
1) **__What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?__**
1) **__Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?__**
1) **__How to implement a user input-line function fully thread-safe?__**
1) **__How to use 'Screenlock' with multi-threading?__**
1) **__How to use 'video paging (double buffering or page flipping)' with multi-threading?__**
1) **__How to use the FB runtime library for multi-threaded applications (gfxlib2) with multi-threading?__**
1) **__How to use console statements and keyboard inputs with multi-threading?__**
Deletions:
1) __When is it not mandatory to protect by a mutex one shared variable between several threads?__
1) __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__
1) __What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?__
1) __Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?__
1) __How to implement a user input-line function fully thread-safe?__
1) __How to use 'Screenlock' with multi-threading?__
1) __How to use 'video paging (double buffering or page flipping)' with multi-threading?__
1) __How to use the FB runtime library for multi-threaded applications (gfxlib2) with multi-threading?__
1) __How to use console statements and keyboard inputs with multi-threading?__


Revision [23419]

Edited on 2019-09-12 11:51:59 by fxm [new page created]
Additions:
----
----
----
----
----
----
----
----
----


Revision [23418]

Edited on 2019-09-12 03:33:42 by fxm [new page created]
Additions:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-3.bas"}}%%(freebasic)
Deletions:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-3.bas"}}%%(freebasic)


Revision [23417]

Edited on 2019-09-12 03:28:14 by fxm [new page created]
Additions:
' Do_something_with_exclusion Do_something_with_exclusion
' CondWait(cond#1, mut) <----------------------- CondSignal(cond#1)
' Do_something_with_exclusion <---------. Do_something_with_exclusion
' CondSignal(cond#2) ------------------ | -----> CondWait(cond#2, mut)
' Do_something_with_exclusion .---- | -----> Do_something_with_exclusion
' MutexUnlock(mut) ---------------' '------- MutexUnlock(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)
' | .....
' | Critical section of code
' | .....
' instructions with only display (printing/drawing, ...)
' instructions with only input without waiting (inkey/mouse getting, ...)
Deletions:
' Do_something_with_exclusion Do_something_with_exclusion
' CondWait(cond#1, mut) <----------------------- CondSignal(cond#1)
' Do_something_with_exclusion <---------. Do_something_with_exclusion
' CondSignal(cond#2) ------------------ | -----> CondWait(cond#2, mut)
' Do_something_with_exclusion .---- | -----> Do_something_with_exclusion
' MutexUnlock(mut) -----------------' '----- MutexUnlock(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)
' | | .....
' | | Critical section of code
' | | .....
Screenlock
' instructions with only display (printing/drawing, ...)
Screenunlock
' instructions with only input without waiting (inkey/mouse getting, ...)


Revision [23415]

Edited on 2019-09-12 02:48:41 by fxm [new page created]
Additions:
{{fbdoc item="title" value="Critical Sections FAQ"}}----
Deletions:
{{fbdoc item="title" value="Critical Sections FAQ (IN PROGRESS...)"}}----


Revision [23414]

Edited on 2019-09-12 02:37:52 by fxm [new page in progress...]

No Differences

Revision [23413]

Edited on 2019-09-11 17:11:13 by fxm [new page in progress...]

No Differences

Revision [23412]

Edited on 2019-09-11 17:09:52 by fxm [new page in progress...]

No Differences

Revision [23411]

Edited on 2019-09-11 17:07:58 by fxm [new page in progress...]

No Differences

Revision [23410]

Edited on 2019-09-11 17:06:04 by fxm [new page in progress...]
Additions:
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
Deletions:
%%@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
%%@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@


Revision [23409]

Edited on 2019-09-11 17:00:24 by fxm [new page in progress...]
Additions:
{{anchor name="ProPgMtCriticalSectionsFAQtop"}}
=={{fbdoc item="section" value="'Critical sections' related questions"}}==
Deletions:
{{anchor name="ProPgMtCriticalSectionsFAQtop"}}=={{fbdoc item="section" value="'Critical sections' related questions"}}==


Revision [23408]

Edited on 2019-09-11 16:59:38 by fxm [new page in progress...]
Additions:
The "**Critical Sections**" related questions".
{{anchor name="ProPgMtCriticalSectionsFAQtop"}}=={{fbdoc item="section" value="'Critical sections' related questions"}}==
Deletions:
{{anchor name="ProPgMtCriticalSectionsFAQtop"}}The "**Critical Sections**" related questions".
=={{fbdoc item="section" value="'Critical sections' related questions"}}==


Revision [23407]

Edited on 2019-09-11 16:58:29 by fxm [new page in progress...]
Additions:
=={{fbdoc item="section" value="'Critical sections' related questions"}}==

----
==@@'Critical sections' related questions@@==
Deletions:
{{fbdoc item="section" value="'Critical sections' related questions"}}


Revision [23406]

Edited on 2019-09-11 16:54:39 by fxm [new page in progress...]
Additions:
%%@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
%%@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
Deletions:
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
%%{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
%%{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@


Revision [23405]

Edited on 2019-09-11 16:51:05 by fxm [new page in progress...]
Additions:
{{anchor name="ProPgMtCriticalSectionsFAQtop"}}The "**Critical Sections**" related questions".
@@{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQ2"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
%%{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQ5"}}
%%{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQ6"}}
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
{{anchor name="ProPgMtCriticalSectionsFAQtop|Back to top"}}@@
Deletions:
The "**Critical Sections**" related questions".
%%{{anchor name="ProPgMtCriticalSectionsFAQ2"}}
%%{{anchor name="ProPgMtCriticalSectionsFAQ5"}}
%%{{anchor name="ProPgMtCriticalSectionsFAQ6"}}


Revision [23404]

Edited on 2019-09-11 16:24:35 by fxm [new page in progress...]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ7|7. How to use 'video paging (double buffering or page flipping)' with multi-threading?"}}**
1) __How to use 'video paging (double buffering or page flipping)' with multi-threading?__
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ7|7. How to use "video paging (double buffering or page flipping)" with multi-threading?"}}**
1) __How to use "video paging (double buffering or page flipping)" with multi-threading?__


Revision [23403]

Edited on 2019-09-11 16:22:25 by fxm [new page in progress...]

No Differences

Revision [23402]

Edited on 2019-09-11 16:21:17 by fxm [new page in progress...]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ2|2. What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ3|3. What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ4|4. Why it is mandatory to put 'Condwait' within a 'While' loop for checking a Boolean predicate (set by other thread before activate 'Condsignal' or 'Condbroadcast')?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ5|5. How to implement a user input-line function fully thread-safe?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ6|6. How to use 'Screenlock' with multi-threading?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ7|7. How to use "video paging (double buffering or page flipping)" with multi-threading?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ8|8. How to use the FB runtime library for multi-threaded applications (gfxlib2) with multi-threading?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ9|9. How to use console statements and keyboard inputs with multi-threading?"}}**
{{anchor name="ProPgMtCriticalSectionsFAQ4"}}
%%{{anchor name="ProPgMtCriticalSectionsFAQ5"}}
%%{{anchor name="ProPgMtCriticalSectionsFAQ6"}}
{{anchor name="ProPgMtCriticalSectionsFAQ7"}}
{{anchor name="ProPgMtCriticalSectionsFAQ8"}}
{{anchor name="ProPgMtCriticalSectionsFAQ9"}}
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ2|1. What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ3|1. What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?"}}**


Revision [23401]

Edited on 2019-09-11 16:11:43 by fxm [new page in progress...]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ2|1. What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ3|1. What happens if calling 'Condsignal()' or 'Condbroadcast()' without mutex locked?"}}**
{{anchor name="ProPgMtCriticalSectionsFAQ3"}}
Deletions:
**{{anchor name="ProPgMtCriticalSectionsFAQ2|2. What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?"}}**


Revision [23400]

Edited on 2019-09-11 16:09:03 by fxm [new page in progress...]
Additions:
%%{{anchor name="ProPgMtCriticalSectionsFAQ2"}}
Deletions:
%%{{anchor name="OVERVIEW"}}


Revision [23399]

Edited on 2019-09-11 16:07:56 by fxm [new page in progress...]
Additions:
**{{anchor name="ProPgMtCriticalSectionsFAQ1|1. When is it not mandatory to protect by a mutex one shared variable between several threads?"}}**
**{{anchor name="ProPgMtCriticalSectionsFAQ2|2. What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?"}}**
{{anchor name="ProPgMtCriticalSectionsFAQ1"}}
Deletions:
**{{anchor name="OVERVIEW|Overview"}}**


Revision [23398]

Edited on 2019-09-11 16:02:53 by fxm [new page in progress...]
Additions:
%%{{anchor name="OVERVIEW"}}
Deletions:
{{anchor name="OVERVIEW"}}


Revision [23397]

Edited on 2019-09-11 16:01:16 by fxm [new page in progress...]
Additions:
{{anchor name="OVERVIEW"}}
1) __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__
Deletions:
{{anchor name="OVERVIEW"}} 1) __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__


Revision [23396]

Edited on 2019-09-11 16:00:26 by fxm [new page in progress...]
Additions:
{{anchor name="OVERVIEW"}} 1) __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__
Deletions:
{{anchor name="OVERVIEW"}}1) __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__


Revision [23395]

Edited on 2019-09-11 15:59:17 by fxm [new page in progress...]
Additions:
**{{anchor name="OVERVIEW|Overview"}}**
{{anchor name="OVERVIEW"}}1) __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__
Deletions:
1) __What is the chronology of code execution of 2 critical sections (with a mutex locking and a conditional variable signaling) that compete between 2 threads?__


Revision [23394]

Edited on 2019-09-11 15:52:24 by fxm [new page in progress...]
Additions:
Console statements (such as ##//Locate//##, ##//Print//##, ##//Color//##, ...), as well as ##//Locate//## and ##//Print//## on Graphics window (but not ##//Color//## on Graphics Window), and keyboard inputs (such as ##//Inkey//##, ##//Getkey//##, ##//Input//##, ...) are not thread-safe:
**""-""** Thus when they are used in competing sections of different threads, mutual exclusion is mandatory by means of mutex locking blocks in which in addition code can restore states (such as text cursor position, console color, ...) at end of the block (after its own usage), as they were before (at begin of the block).
**""-""** But the ##//Getkey//## or ##//Input//## keyword cannot be enclosed inside a mutex locking block (as it can be do with the ##//Inkey//## keyword), because as long as the keyboard input is not completed, the other threads in compete would be fully blocked (waiting for the mutex unlocking).
**""-""** Example showing that the keywords ##//Locate//## and ##//Print//## are not thread-safe both when applied on a console window or when applied on a graphics window (the text cursor states being not thread dependent in the two cases):
Locate Cast(Integer, p), Cast(Integer, p)
For I As Integer = 1 To 50 - 2 * Cast(Integer, p)
Sleep 20 * Cast(Integer, p), 1
Print Str(Cast(Integer, p));
Sub test ()
Dim As Any Ptr p(1 To 9)
For I As Integer = 1 To 9
p(I) = Threadcreate(@Thread, Cast(Any Ptr, I))
Sleep 25, 1
For I As Integer = 1 To 9
Threadwait(p(I))
Screen 0
test()
Locate 15, 1
Print "Any key to continue"
test()
Locate 15, 1
Print "Any key to quit"
%%Note: One can see that each thread does not write on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.

**""-""** From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring cursor states before/after its own cursor moving:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-1.bas"}}%%(freebasic)
Dim As Long l0 = Locate()
Locate Cast(Integer, p), Cast(Integer, p)
Dim As Long l = Locate()
Locate Hibyte(Loword(l0)), Lobyte(Loword(l0)), Hiword(l0)
For I As Integer = 1 To 50 - 2 * Cast(Integer, p)
Sleep 20 * Cast(Integer, p), 1
l0 = Locate()
Locate Hibyte(Loword(l)), Lobyte(Loword(l)), Hiword(l)
Print Str(Cast(Integer, p));
l = Locate()
Locate Hibyte(Loword(l0)), Lobyte(Loword(l0)), Hiword(l0)
Sub test ()
Dim As Any Ptr p(1 To 9)
For I As Integer = 1 To 9
p(I) = Threadcreate(@Thread, Cast(Any Ptr, I))
Sleep 25, 1
For I As Integer = 1 To 9
Threadwait(p(I))
Screen 0
test()
Locate 15, 1
Print "Any key to continue"
test()
Locate 15, 1
Print "Any key to quit"
%%Note: One can see that each thread writes now on its own line corresponding to its thread number (id between 1 and 9), on the console window and on the graphics window.

**""-""** Example showing that the ##//Color//## keyword is not thread-safe when applied on a console window, but is thread-safe when applied on a graphics window (the color states being thread dependent in that case):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-2.bas"}}%%(freebasic)
Color Cast(Integer, p) + 8, Cast(Integer, p)
For I As Integer = 1 To 50 - 2 * Cast(Integer, p)
Print " " & Cast(Integer, p) & " ";
Sleep 20 * Cast(Integer, p), 1
Sub test ()
Dim As Any Ptr p(1 To 9)
Locate 1, 1
For I As Integer = 1 To 9
p(I) = Threadcreate(@Thread, Cast(Any Ptr, I))
Sleep 25, 1
For I As Integer = 1 To 9
Threadwait(p(I))
Locate 16, 1
Screen 0
test()
Print "Any key to continue"
test()
Print "Any key to quit"
%%Note: One can see that the foreground/background colors are not specific to the thread number (id between 1 and 9) on the console window, but this works great on the graphics window.

**""-""** From the above example, the thread code has been completed in its competing sections by mutex locking blocks and by saving/restoring color states before/after its own color values usage:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-3.bas"}}%%(freebasic)
Dim As Ulong c0 = Color(Cast(Integer, p) + 8, Cast(Integer, p))
Dim As Ulong c = Color()
Color(Loword(c0), Hiword(c0))
For I As Integer = 1 To 50 - 2 * Cast(Integer, p)
c0 = Color(Loword(c), Hiword(c))
Print " " & Cast(Integer, p) & " ";
Color(Loword(c0), Hiword(c0))
Sleep 20 * Cast(Integer, p), 1
Sub test ()
Dim As Any Ptr p(1 To 9)
Locate 1, 1
For I As Integer = 1 To 9
p(I) = Threadcreate(@Thread, Cast(Any Ptr, I))
Sleep 25, 1
For I As Integer = 1 To 9
Threadwait(p(I))
Locate 16, 1
Screen 0
test()
Print "Any key to continue"
test()
Print "Any key to quit"
%%Note: One can see that the foreground/background colors are now specific to the thread number (id between 1 and 9) on the console window (obviously this always works on the graphics window).

Therefore, for using Getkey or Input in competing sections of threads:
**""-""** Only a single thread (for example, the main thread) can uses ##//Getkey//## or ##//Input//## in addition to console statements (such as ##//Locate//##, ##//Print//##, ##//Color//##, ...) and also ##//Inkey//##, in its competing sections.
**""-""** The other threads must not to use in their competing sections any console statement neither any keyboard input keyword, but can use by cons graphics statements (such as ##//Pset//##, ##//Line//##, ##//Circle//##, ##//Draw String//##, graphic ##//Color//##, ...) which are themselves thread-safe (they can interlace graphically with the main thread without any problem).
**""-""** ##//Input//## and ##//Getkey//## also exclude the screen locking usage in competing sections of threads (double buffering is recommended as anti-flickering method).
**""-""** Example showing that graphics statements (such as ##//Line//## and ##//Draw String//## and ##//Screencopy//##) in a thread (user thread here) can compete with console statements (such as ##//Locate//## and ##//Print//## and ##//Input//##) in another thread (main thread here), without using any exclusion (by mutex):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-4.bas"}}%%(freebasic)
Line (16, 432)-Step(96, 32), 11, BF 'clear the print area
Print "Enter ""quit"" to quit"
Locate 3, 2
Print Space(Len(reply) + 2);
Locate 3, 2
Input reply
Loop Until Lcase(reply) = "quit"
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).

**""-""** From the above example, if the date displaying and the time displaying are now two separate user threads, an exclusion mutex code block between these two threads only is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two user threads only:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq9-5.bas"}}%%(freebasic)
Print "Enter ""quit"" to quit"
Locate 3, 2
Print Space(Len(reply) + 2);
Locate 3, 2
Input reply
Loop Until Lcase(reply) = "quit"
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used (screen locking being forbidden by Input usage).
Deletions:
.....


Revision [23393]

Edited on 2019-09-11 15:01:32 by fxm [new page in progress...]
Additions:
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' lines is only here to highlight the flickering if no screen locking is used.
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used, or if no mutex is used.
Deletions:
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no screen locking is used.
%%Note: The Sleep keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used, or if no mutex is used.


Revision [23392]

Edited on 2019-09-11 14:41:14 by fxm [new page in progress...]
Additions:
The source code of gfxlib2 uses TLS (Thread Local Storage) to store many states, so many things are thread-specific.
Since gfxlib2 is thread-safe, mutex exclusion between threads is not necessary for the graphics statements themselves (including ##//Draw String//##).
In contrast, console statements such as ##//Locate//##, ##//Print//##, ... are not thread-safe as previously mentioned (for example, text cursor position is common to all threads).
**""-""** Simple example showing that graphic states (such as graphic cursor position, graphic colors) are thread-dependent:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-1.bas"}}%%(freebasic)
Sub thread(Byval p As Any Ptr)
Color 10
Pset(150, 10)
For I As Integer = 1 To 40
Line -Step(10, 10)
Sleep 150, 1
Draw String Step (-40, 10), "user thread"
Dim As Any Ptr p = Threadcreate(@thread)
Color 14
Pset(10, 100)
For I As Integer = 1 To 24
Line -Step(10, 10)
Sleep 250, 1
Draw String Step (-40, 10), "main thread"
Threadwait(p)
Color 15
Locate 4, 2
Print "Any key for exit"
**""-""** Example showing that graphics statements (such as Line and Draw String and Screencopy) in a thread can compete with console statements (such as Inkey) in another thread, without using any exclusion (by mutex):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-2.bas"}}%%(freebasic)
#include "vbcompat.bi"
Screenset 1, 0
Color 0, 7
Cls
Dim Shared terminate As Integer = 0
Sub thread (byval param As Any Ptr)
Screenset 1, 0
Line (16, 432)-Step(96, 32), 11, BF 'clear print area
Draw String (24, 432), Format(Now,"dd/mm/yyyy"), 0
Draw String (32, 448), Format(Now,"hh:mm:ss"), 0
Screencopy
Loop Until terminate = 1
Dim As String reply
Locate 2, 2
Print "Enter ""q"" to quit"
Dim p As Any Ptr = ThreadCreate(@thread)
reply = Inkey
Loop Until Lcase(reply) = "q"
Print " Stop the thread"
terminate=1
Threadwait (p)
Print " Thread terminated"
%%Note: The Sleep keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used.
**""-""** From the above example, if the date displaying and the time displaying are now two separate threads, an exclusion mutex code block between these two threads is mandatory, not due to the graphics statements themselves competing, but only due to the double buffering method used (against flickering) that puts competing these two threads:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq8-3.bas"}}%%(freebasic)
#include "vbcompat.bi"
Screenset 1, 0
Color 0, 7
Cls
Dim Shared terminate As Integer = 0
Dim Shared mutex As Any Ptr
Sub thread1 (byval param As Any Ptr)
Screenset 1, 0
Line (16, 432)-Step(96, 16), 11, BF 'clear the print area
Sleep 200, 1
Draw String (24, 432), Format(Now,"dd/mm/yyyy"), 0
Screencopy
Loop Until terminate = 1
Sub thread2 (byval param As Any Ptr)
Screenset 1, 0
Line (16, 448)-Step(96, 16), 11, BF 'clear the print area
Draw String (32, 448), Format(Now,"hh:mm:ss"), 0
Screencopy
Loop Until terminate = 1
Dim As String reply
Locate 2, 2
Print "Enter ""q"" to quit"
mutex = Mutexcreate
Dim p1 As Any Ptr = ThreadCreate(@thread1)
Dim p2 As Any Ptr = ThreadCreate(@thread2)
reply = Inkey
Loop Until Lcase(reply) = "q"
Print " Stop the threads"
terminate=1
Threadwait (p1)
Threadwait (p2)
Print " Threads terminated"
%%Note: The Sleep keyword just after the 'clear the print area' line is only here to highlight the flickering if no double buffering is used, or if no mutex is used.


Revision [23391]

Edited on 2019-09-11 14:23:37 by fxm [new page in progress...]
Additions:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq6.bas"}}%%(freebasic)
Instead of "screen locking" (see the above paragraph), "video paging (double buffering or page flipping)" can more simply be used with multi-threading, but be careful that many states in the gfxlib2 are thread-dependent like ##//Screenset//## (and also ##//View//## settings, graphic cursor position, graphic colors, ...).
Therefore, the setting for the working page and the visible page must always be controlled in each thread code which want to work with a multi-video page configuration.
**""-""** Example for a double buffering method (at each step, each thread needs to update the working page and copy it to the visible page, from within an exclusion mutex code block):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-1.bas"}}%%(freebasic)
Screenset 1, 0 '' setting to define in each thread
Line (544, 0)-(639, 49), 0, BF '' clear the print area
Screencopy
Screen 12, , 2
Screenset 1, 0 '' setting to define in each thread
Screencopy
Dim s As String
Line (296, 208)-(376, 256), 0, BF '' clear the print area
Screencopy
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no double buffering is used.
**""-""** Example for a two page flipping method (at each step, each thread needs to update and flip, from within the same exclusion mutex code block, the two screen pages):
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq7-2.bas"}}%%(freebasic)
Dim p0 As Integer = 0
Dim p1 As Integer = 1
Screenset 1, 0 '' setting to define in each thread
Dim s As String = ClockTime()
For I As Integer = 1 To 2 '' updating the two screen pages
Line (544, 0)-(639, 49), 0, BF '' clear the print area
Sleep 100, 1
Locate 2, 71
Print s;
Screenset p0, p1
Swap p0, p1
Next I
Screen 12, , 2
Dim p0 As Integer = 0
Dim p1 As Integer = 1
Screenset 1, 0 '' setting to define in each thread
For I As Integer = 1 To 2 '' updating the two screen pages
Locate 30, 2
Print "<q/Q> : quit";
Screenset p0, p1
Swap p0, p1
Dim s As String
Dim C As Integer = Counter()
For I As Integer = 1 To 2 '' updating the two screen pages
Line (296, 208)-(376, 256), 0, BF '' clear the print area
Sleep 100, 1
Locate 15,40
Print Using "######"; c;
Screenset p0, p1
Swap p0, p1
Next I
%%Note: The Sleep keyword just after the 'clear the print area' lines is only here to highlight the flickering if no two page flipping is used.
**Note:** In these two examples, an exclusion mutex code block is mandatory in the two threads, not only because of using console statements + ##//Inkey//##, but around also the graphics statements + ##//Screencopy//## only because of using double buffering method (without anti-flickering process, the graphics statements could be outside the exclusion mutex code block).
Deletions:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)


Revision [23390]

Edited on 2019-09-11 13:51:11 by fxm [new page in progress...]
Additions:
Dim As Integer r
Dim As Integer c
Dim As String inputchr
Dim As String inputline
r = Csrlin()
c = Pos()
Locate row, column + Len(inputline) + Len(prompt) + 2
inputchr = Inkey
If Len(inputchr) = 1 Then
If Asc(inputchr) >= 32 Then
Print inputchr & Chr(95);
Locate , pos - 1
inputline &= inputchr
Elseif Asc(inputchr) = 08 and Len(inputline) > 0 Then
Locate , pos - 1
Print chr(95) & " ";
Locate , Pos() - 2
inputline = Left(inputline, Len(inputline) - 1)
End If
Locate r, c
Sleep sleeptime, 1
Loop Until inputchr = Chr(13)
If blank <> 0 Then
r = Csrlin()
c = Pos()
Locate row, column + Len(prompt) + 2
Print Space(Len(inputline) + 1);
Locate r, c
Return inputline
Dim As Integer r
Dim As Integer c
Dim As String inputchr
Dim As String inputline
r = Csrlin()
c = Pos()
Locate row, column + Len(inputline) + Len(prompt) + 2
inputchr = Inkey
If Len(inputchr) = 1 Then
If Asc(inputchr) >= 32 Then
Print inputchr & Chr(95);
Locate , pos - 1
inputline &= inputchr
Elseif Asc(inputchr) = 08 and Len(inputline) > 0 Then
Locate , pos - 1
Print chr(95) & " ";
Locate , Pos() - 2
inputline = Left(inputline, Len(inputline) - 1)
End If
Locate r, c
Sleep sleeptime, 1
Loop Until inputchr = Chr(13)
If blank <> 0 Then
r = Csrlin()
c = Pos()
Locate row, column + Len(prompt) + 2
Print Space(Len(inputline) + 1);
Locate r, c
Return inputline
Dim As Integer number
Dim As Integer tempo
Dim As Any Ptr pThread
Dim As Ulongint count
Static As Any Ptr pMutex
Static As Integer numberMax
Static As Integer quit
With *pt
Locate .number, .number, 0
Sleep 5, 1
.count += 1
Print .count;
End With
Dim As Integer quit
Dim As UDT Ptr pUDT = p
With *pUDT
Do
Mutexlock(.pMutex)
Counter(pUDT)
quit = .quit
Mutexunlock(.pMutex)
Sleep .tempo, 1
Loop Until quit = 1
End With
u(I).number = i
u(I).tempo = 100 + 15 * I - 95 * Sgn(I)
u(I).pThread = Threadcreate(@Thread, @u(I))
Threadwait(u(I).pThread)
c += u(I).count
**""-""** ##//Screenlock...Scrennunlock//## blocks are not compatible with multi-threading (otherwise, the program hangs). This is why a mutex block must be used around each such block to ensure the exclusion.
**""-""** The input keywords (like for keyboard, mouse) cannot be safely run when the screen is locked, therefore a such keyword must be outside of any ##//Screenlock...Screenunlock//## block, so outside any ##//Screenlock...Screenunlock//## block in its own thread, and protected of all ##//Screenlock...Screenunlock//## blocks of other threads by a mutex block. Therefore, ##//Getkey//## and ##//Input//##, the statements that wait for keypress or line input are unusable, but ##//Inkey//## that does not wait can work.
By applying some rules scrupulously, one can use ##//Screenlock//##/##//Screenunlock//## inside the threads.
Principle of coding for all threads including the main code (main thread):
' instructions without display (printing/drawing, ...) neither input (input/inkey/mouse getting, ...)
MutexLock(m)
Screenlock
' instructions with only display (printing/drawing, ...)
Screenunlock
' instructions with only input without waiting (inkey/mouse getting, ...)
MutexUnlock(m)
Sleep tempo
Loop Until condition
For example, it is mandatory to use one ##//Mutexlock...Mutexunlock//## block around each ##//Screenlock...Screenunlock//## block, and one other around the ##//Inkey//## instruction which itself must always be outside of any ##//Screenlock...Screenunlock//## bloc:
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)
Type ThreadUDT
Dim handle As Any Ptr
Static sync As Any Ptr
Static quit As Byte
Dim ThreadUDT.sync As Any Ptr
Dim ThreadUDT.quit As Byte
Function ClockTime () As String
Return Time
Function Counter () As Integer
Static C As Integer
C = (C + 1) MOD 1000000
Return C
Sub ProcedureThread (Byval param As Any Ptr)
With *Cast(ThreadUDT Ptr, param)
Do
MutexLock(.sync)
Screenlock
Line (544, 0)-(639, 49), 0, BF 'clear the print area
Sleep 100, 1
Locate 2, 71
Print ClockTime();
Screenunlock
MutexUnlock(.sync)
Sleep 100, 1
Loop Until .quit = 1
End With
Locate 30, 2
Print "<q/Q> : quit";
Dim TTptr As ThreadUDT Ptr = New ThreadUDT
ThreadUDT.sync = MutexCreate
TTptr->handle = ThreadCreate(@ProcedureThread, TTptr)
Dim As String s
MutexLock(ThreadUDT.sync)
Screenlock
Line (296, 208)-(376, 256), 0, BF 'clear the print area
Sleep 100, 1
Locate 15,40
Print Using "######"; Counter();
Screenunlock
s = Inkey
MutexUnlock(ThreadUDT.sync)
Sleep 100, 1
Loop Until Lcase(s) = "q"
ThreadUDT.quit = 1
ThreadWait(TTptr->handle)
MutexDestroy(ThreadUDT.sync)
Delete TTptr
%%Note: The ##//Sleep//## keyword just after the 'clear the print area' line is only here to highlight the flickering if no screen locking is used.
Deletions:
Dim As Integer r
Dim As Integer c
Dim As String inputchr
Dim As String inputline
Mutexlock(mutex)
Mutexunlock(mutex)
Do
r = Csrlin()
c = Pos()
Locate row, column + Len(inputline) + Len(prompt) + 2
inputchr = Inkey
If Len(inputchr) = 1 Then
If Asc(inputchr) >= 32 Then
Print inputchr & Chr(95);
Locate , pos - 1
inputline &= inputchr
Elseif Asc(inputchr) = 08 and Len(inputline) > 0 Then
Locate , pos - 1
Print chr(95) & " ";
Locate , Pos() - 2
inputline = Left(inputline, Len(inputline) - 1)
End If
Locate r, c
Sleep sleeptime, 1
Loop Until inputchr = Chr(13)
If blank <> 0 Then
r = Csrlin()
c = Pos()
Locate row, column + Len(prompt) + 2
Print Space(Len(inputline) + 1);
Locate r, c
End If
Return inputline
Dim As Integer r
Dim As Integer c
Dim As String inputchr
Dim As String inputline
Mutexlock(mutex)
Mutexunlock(mutex)
Do
r = Csrlin()
c = Pos()
Locate row, column + Len(inputline) + Len(prompt) + 2
inputchr = Inkey
If Len(inputchr) = 1 Then
If Asc(inputchr) >= 32 Then
Print inputchr & Chr(95);
Locate , pos - 1
inputline &= inputchr
Elseif Asc(inputchr) = 08 and Len(inputline) > 0 Then
Locate , pos - 1
Print chr(95) & " ";
Locate , Pos() - 2
inputline = Left(inputline, Len(inputline) - 1)
End If
Locate r, c
Sleep sleeptime, 1
Loop Until inputchr = Chr(13)
If blank <> 0 Then
r = Csrlin()
c = Pos()
Locate row, column + Len(prompt) + 2
Print Space(Len(inputline) + 1);
Locate r, c
End If
Return inputline
Dim As Integer number
Dim As Integer tempo
Dim As Any Ptr pThread
Dim As Ulongint count
Static As Any Ptr pMutex
Static As Integer numberMax
Static As Integer quit
With *pt
Locate .number, .number, 0
Sleep 5, 1
.count += 1
Print .count;
End With
Dim As Integer quit
Dim As UDT Ptr pUDT = p
With *pUDT
Mutexlock(.pMutex)
Counter(pUDT)
quit = .quit
Mutexunlock(.pMutex)
Sleep .tempo, 1
End With
u(I).number = i
u(I).tempo = 100 + 15 * I - 95 * Sgn(I)
u(I).pThread = Threadcreate(@Thread, @u(I))
Threadwait(u(I).pThread)
c += u(I).count


Revision [23389]

Edited on 2019-09-11 12:55:13 by fxm [new page in progress...]
Additions:
In the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]## "Synchronous method example using a condwait then a condbroadcast (and a mutex) for all threads":
Deletions:
In the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]##:


Revision [23388]

Edited on 2019-09-11 12:41:18 by fxm [new page in progress...]
Additions:
%%(freebasic)
Function threadInput (Byval row As Integer, Byval column As Integer, Byref prompt As String = "", Byval sleeptime As Integer = 15, Byval blank As Integer = 0, Byval mutex As Any Ptr = 0) As String
Dim As Integer r
Dim As Integer c
Dim As String inputchr
Dim As String inputline
Mutexlock(mutex)
r = Csrlin()
c = Pos()
Locate row, column
Print prompt & "? _";
Locate r, c
Mutexunlock(mutex)
Do
r = Csrlin()
c = Pos()
Locate row, column + Len(inputline) + Len(prompt) + 2
inputchr = Inkey
If Len(inputchr) = 1 Then
If Asc(inputchr) >= 32 Then
Print inputchr & Chr(95);
Locate , pos - 1
inputline &= inputchr
Elseif Asc(inputchr) = 08 and Len(inputline) > 0 Then
Locate , pos - 1
Print chr(95) & " ";
Locate , Pos() - 2
inputline = Left(inputline, Len(inputline) - 1)
End If
Locate r, c
Sleep sleeptime, 1
Loop Until inputchr = Chr(13)
If blank <> 0 Then
r = Csrlin()
c = Pos()
Locate row, column + Len(prompt) + 2
Print Space(Len(inputline) + 1);
Locate r, c
End If
Return inputline
End Function
%%
From the example 1 on the ##[[ProPgMtCriticalSections|Critical Sections]]## page "Asynchronous method example using a mutex for all threads", now the running multi-threading code is waiting for the "quit" command in order to exit the program:
%%
' User thread algorithm:
' Do
' | Mutexlock
' | | .....
' | | Critical section of code
' | | .....
' | Mutexunlock
' | Sleep my_tempo
' Loop Until quit = true
' There is no any advantage or disadvantage between threads for running their critical sections.
%%
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq5.bas"}}%%(freebasic)
Function threadInput (Byval row As Integer, Byval column As Integer, Byref prompt As String = "", Byval sleeptime As Integer = 15, Byval blank As Integer = 0, Byval mutex As Any Ptr = 0) As String
Dim As Integer r
Dim As Integer c
Dim As String inputchr
Dim As String inputline
Mutexlock(mutex)
r = Csrlin()
c = Pos()
Locate row, column
Print prompt & "? _";
Locate r, c
Mutexunlock(mutex)
Do
r = Csrlin()
c = Pos()
Locate row, column + Len(inputline) + Len(prompt) + 2
inputchr = Inkey
If Len(inputchr) = 1 Then
If Asc(inputchr) >= 32 Then
Print inputchr & Chr(95);
Locate , pos - 1
inputline &= inputchr
Elseif Asc(inputchr) = 08 and Len(inputline) > 0 Then
Locate , pos - 1
Print chr(95) & " ";
Locate , Pos() - 2
inputline = Left(inputline, Len(inputline) - 1)
End If
Locate r, c
Sleep sleeptime, 1
Loop Until inputchr = Chr(13)
If blank <> 0 Then
r = Csrlin()
c = Pos()
Locate row, column + Len(prompt) + 2
Print Space(Len(inputline) + 1);
Locate r, c
End If
Return inputline
End Function
Type UDT
Dim As Integer number
Dim As Integer tempo
Dim As Any Ptr pThread
Dim As Ulongint count
Static As Any Ptr pMutex
Static As Integer numberMax
Static As Integer quit
End Type
Dim As Any Ptr UDT.pMutex
Dim As Integer UDT.numberMax
Dim As Integer UDT.quit
Sub Counter (Byval pt As UDT Ptr)
With *pt
Locate .number, .number, 0
Sleep 5, 1
.count += 1
Print .count;
End With
Sub Thread (Byval p As Any Ptr)
Dim As Integer quit
Dim As UDT Ptr pUDT = p
With *pUDT
Mutexlock(.pMutex)
Counter(pUDT)
quit = .quit
Mutexunlock(.pMutex)
Sleep .tempo, 1
End With
UDT.numberMax = 6
Dim As UDT u(0 To UDT.numberMax)
For I As Integer = 0 To UDT.numberMax
u(I).number = i
u(I).tempo = 100 + 15 * I - 95 * Sgn(I)
Next I
UDT.pMutex = Mutexcreate
Dim As Single t = Timer
For I As Integer = 1 To UDT.numberMax
u(I).pThread = Threadcreate(@Thread, @u(I))
Next I
Loop Until Lcase(threadInput(8, 1, """quit"" for exit", 10, 1, UDT.pMutex)) = "quit"
UDT.quit = 1
For I As Integer = 1 To UDT.numberMax
Threadwait(u(I).pThread)
Next I
t = Timer - t
Mutexdestroy(UDT.pMutex)
Dim As Ulongint c
For I As Integer = 1 to UDT.numberMax
c += u(I).count
Next I
Locate UDT.numberMax + 4, 1
Print Culngint(c / t) & " increments per second"
%%
Deletions:


Revision [23386]

Edited on 2019-09-11 11:38:56 by fxm [new page in progress...]
Additions:
The ##//Input//## keyword may be not thread-safe, when another thread must also access to input/output resource:
**""-""** When executing the ##//Input//## statement, the other running threads must not change the position of the text cursor, which prohibits instructions such as ##//Locate//##, ##//Print//##, ...
**""-""** Moreover, one cannot enclosed the ##//Input//## keyword inside a mutex locking (as we can do it for the ##//Inkey//## keyword), because while the inputting line would be not completed and validated, the other threads that want to also access to input/output would be fully blocked (waiting for mutex unlocking).
- Thread-safe input-line function (versus input/output resource):
Input position, prompt message, sleeping time, line-blanking command, mutex pointer can be passed to the following ##//threadInput()//## function that simulates a simplified input function, but thread-safe, by using a looping around the ##//Inkey//## keyword (all input/output keywords must be enclosed inside a mutex locking block, and the cursor position must be restored at each mutex locking block ending):


Revision [23384]

Edited on 2019-09-11 11:27:41 by fxm [new page in progress...]
Additions:
**##//While predicate <> True
predicate = False//##**
Deletions:
##//While predicate <> True
predicate = False//##


Revision [23383]

Edited on 2019-09-11 11:24:13 by fxm [new page in progress...]
Additions:
##//While predicate <> True
Condwait(conditionalid, mutexid)
Wend
predicate = False//##
In all documentations, it is highly advisable to do so, mainly justified to fight against eventual spurious wake-ups.
This is probably true, but it is also advisable to do so to avoid to loose a ##//""CondSignal""//## (or ##//""CondBroadcast""//##) if it is prematurely activated while the receiving thread is not yet waiting on ##//""CondWait""//## (the signal is lost forever):
**""-""** In that case, the receiving thread has even not yet locked the mutex before that ##//""CondSignal""//## (or ##//""CondBroadcast""//##) is activated.
**""-""** So the predicate will already true before the receiving thread reaches the While loop, inducing that ##//""CondWait""//## is downright skipped, so avoiding a definitive blocking phenomenon.
Let two threads (thread #0 in main program, thread #1 in a user procedure, each that prints its number in a loop), having about the same execution time, and each one synchronizing the other in order to well interlace their numbers (by using one mutex, two condition variables and ##//""CondSignal""//##/##//""CondWait""//##):
**""-""** Without a While loop on predicate, the program hangs quickly (Ctrl-C to quit):
' Thread#0 XOR + <==> Thread#1
' ..... .....
' MutexLock(mut) MutexLock(mut)
' Do_something_with_exclusion Do_something_with_exclusion
' CondWait(cond#1, mut) <----------------------- CondSignal(cond#1)
' Do_something_with_exclusion <---------. Do_something_with_exclusion
' CondSignal(cond#2) ------------------ | -----> CondWait(cond#2, mut)
' Do_something_with_exclusion .---- | -----> Do_something_with_exclusion
' MutexUnlock(mut) -----------------' '----- MutexUnlock(mut)
' ..... .....
%%(freebasic)
Dim Shared As Any Ptr cond1
Dim Shared As Any Ptr cond2
Mutexlock(mutex)
Print "1";
CondSignal(cond1)
CondWait(cond2, mutex)
If quit = 1 Then
Mutexunlock(mutex)
Exit DO
End If
Mutexunlock(mutex)
Sleep 1, 1
Loop
cond1 = CondCreate
cond2 = CondCreate
handle = ThreadCreate(@Thread)
CondWait(cond1, mutex)
Print "0";
CondSignal(cond2)
If Inkey <> "" Then
quit = 1
Mutexunlock(mutex)
Exit Do
End If
Sleep 1, 1
Loop
CondDestroy(cond1)
CondDestroy(cond2)
Print
**""-""** With a While loop on predicate around each ##//""CondWait""//##, no blocking phenomenon:
' Thread#0 XOR + <==> Thread#1
' ..... .....
' 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)
' ..... .....
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq4.bas"}}%%(freebasic)
Dim Shared As Any Ptr cond1
Dim Shared As Any Ptr cond2
Dim Shared As Integer new1
Dim Shared As Integer new2
Mutexlock(mutex)
Print "1";
new1 = 1
CondSignal(cond1)
While new2 <> 1
CondWait(cond2, mutex)
Wend
new2 = 0
If quit = 1 Then
Mutexunlock(mutex)
Exit DO
End If
Mutexunlock(mutex)
Sleep 1, 1
Loop
cond1 = CondCreate
cond2 = CondCreate
handle = ThreadCreate(@Thread)
While new1 <> 1
CondWait(cond1, mutex)
new1 = 0
Print "0";
new2 = 1
CondSignal(cond2)
If Inkey <> "" Then
quit = 1
Mutexunlock(mutex)
Exit Do
End If
Sleep 1, 1
Loop
CondDestroy(cond1)
CondDestroy(cond2)
Print


Revision [23382]

Edited on 2019-09-11 10:50:26 by fxm [new page in progress...]
Additions:
' Sleep 5, 1
' Sleep 5, 1
Sleep *Cast(Integer Ptr, param), 1
Sleep *Cast(Integer Ptr, param), 1
Sleep 1000, 1
Deletions:
' Sleep 5
' Sleep 5
Sleep *Cast(Integer Ptr, param)
Sleep *Cast(Integer Ptr, param)
Sleep 1000


Revision [23381]

Edited on 2019-09-11 10:44:38 by fxm [new page in progress...]
Additions:
**Note:** If ##//""CondWait""//## is not within a ##//While//## loop on predicate (by putting in comment the first line of above program), one can check in the second case (thread#1 signaling before thread#0 waiting), that thread#0 remains blocked in its waiting phase (Ctrl-C to quit).
Referring to the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]##, one takes this opportunity to recall that:
**""-""** The mutex must always be also locked while executing ##//""Condsignal()""//## or ##//""Condbroadcast()""//## to wake up a thread (it may be unlocked but only after ##//""Condsignal()""//## or ##//""Condbroadcast()""//##).
**""-""** If the mutex is not locked (or even if the mutex is unlocked only just before executing ##//""Condsignal()""//## or ##//""Condbroadcast()""//##), the behavior may become unpredictable (it may work or not, depending on the threads configuration and execution real time).
In the example 2 on the ##[[ProPgMtCriticalSections|Critical Sections]]##:
**""-""** If one at least ##//Mutexunlock()//## is moved just before its ##//""Condbroadcast()""//##, the program hangs very quickly.
**""-""** Although some users certify that the mutex can always be unlocked just before ##//""Condsignal()""//## or ##//""Condbroadcast()""//##, and others more cautious assert that one can do it only for a ##//""Condbroadcast()""//##, experiment shows the opposite!
The general rule is that:
**""-""** The condition must not be signaled (by ##//""Condsignal()""//## or ##//""Condbroadcast()""//##) between the time a thread locks the mutex and the time it waits on the condition variable (##//""CondWait()""//##), otherwise it seems that it may damage the waiting queue of threads on that condition variable.
**""-""** Thus to avoid that and follow this rule, it is necessary that the mutex remains locked when the condition is signaled.
Deletions:
If ##//""CondWait""//## is not within a ##//While//## loop on predicate (by putting in comment the first line of above program), one can check in the second case (thread#1 signaling before thread#0 waiting), that thread#0 remains blocked in its waiting phase (Ctrl-C to quit).


Revision [23380]

Edited on 2019-09-11 10:24:19 by fxm [new page in progress...]
Additions:
**""-""** But if this is for example one shared variable ##//""LongInt""//## with a win32 compilation, it is advised here to use a mutex (otherwise the reading phase by a thread may be interlaced with the writing phase of another thread).
This behavior can be checked with a graphic program using two threads and a shared ##//""LongInt""//## (64-bit) without mutex:
Chronology for one thread signaling which occurs:
a) while another thread is waiting (within a While loop on predicate),
b) before another thread is waiting (within a While loop on predicate).
{{fbdoc item="filename" value="examples/manual/proguide/multithreading/criticalsectionfaq2.bas"}}%%(freebasic)
#define while_loop_on_predicate
Dim Shared As Any Ptr cond
Dim As Integer sleep0
Dim As Integer sleep1
#ifdef while_loop_on_predicate
Dim Shared As Integer ready
#endif
Sub Thread1 (ByVal param As Any Ptr)
Sleep *Cast(Integer Ptr, param)
Mutexlock(mutex)
Color 11 : Print " Thread#1 locks the mutex"
Color 11 : Print " Thread#1 executes code with exclusion"
#ifdef while_loop_on_predicate
ready = 1
#endif
Color 11 : Print " Thread#1 is signaling"
CondSignal(cond)
Color 11 : Print " Thread#1 executes post-code with exclusion"
Color 11 : Print " Thread#1 unlocks the mutex"
Mutexunlock(mutex)
Sub Thread0 (ByVal param As Any Ptr)
Sleep *Cast(Integer Ptr, param)
Mutexlock(mutex)
Color 10 : Print " Thread#0 locks the mutex"
Color 10 : Print " Thread#0 executes pre-code with exclusion"
#ifdef while_loop_on_predicate
While ready <> 1
#endif
Color 10 : Print " Thread#0 is waiting"
CondWait(cond, mutex)
Color 10 : Print " Thread#0 is waked"
#ifdef while_loop_on_predicate
Wend
#endif
Color 10 : Print " Thread#0 executes code with exclusion"
#ifdef while_loop_on_predicate
ready = 0
#endif
Color 10 : Print " Thread#0 unlocks the mutex"
Mutexunlock(mutex)
cond = CondCreate
sleep0 = 0
sleep1 = 1000
Color 7 : Print "Chronology for Thread#1 signaling while Thread#0 is waiting:"
handle = ThreadCreate(@Thread1, @sleep1)
Thread0(@sleep0)
Color 7 : Print "Thread#1 finished": Print
Sleep 1000
sleep0 = 1000
sleep1 = 0
Color 7 : Print "Chronology for Thread#1 signaling before Thread#0 is waiting:"
handle = ThreadCreate(@Thread1, @sleep1)
Thread0(@sleep0)
Color 7 : Print "Thread#1 finished": Print
CondDestroy(cond)
Sleep
Output part a - Chronology for Thread#1 signaling while Thread#0 is waiting:
%%
Chronology for Thread#1 signaling while Thread#0 is waiting:
Thread#0 locks the mutex
Thread#0 executes pre-code with exclusion
Thread#0 is waiting
Thread#1 locks the mutex
Thread#1 executes code with exclusion
Thread#1 is signaling
Thread#1 executes post-code with exclusion
Thread#1 unlocks the mutex
Thread#0 is waked
Thread#0 executes code with exclusion
Thread#0 unlocks the mutex
Thread#1 finished
%%
Output part b - Chronology for Thread#1 signaling before Thread#0 is waiting:
%%
Chronology for Thread#1 signaling before Thread#0 is waiting:
Thread#1 locks the mutex
Thread#1 executes code with exclusion
Thread#1 is signaling
Thread#1 executes post-code with exclusion
Thread#1 unlocks the mutex
Thread#0 locks the mutex
Thread#0 executes pre-code with exclusion
Thread#0 executes code with exclusion
Thread#0 unlocks the mutex
Thread#1 finished
%%
If ##//""CondWait""//## is not within a ##//While//## loop on predicate (by putting in comment the first line of above program), one can check in the second case (thread#1 signaling before thread#0 waiting), that thread#0 remains blocked in its waiting phase (Ctrl-C to quit).
Deletions:
**""-""** But if this is for example one shared variable ##//LongInt//## with a win32 compilation, it is advised here to use a mutex (otherwise the reading phase by a thread may be interlaced with the writing phase of another thread).
This behavior can be checked with a graphic program using two threads and a shared ##//LongInt//## (64-bit) without mutex:


Revision [23379]

Edited on 2019-09-11 09:53:29 by fxm [new page in progress...]
Additions:
{{fbdoc item="section" value="See also"}}
- [[ProPgMultiThreading|Multi-Threading]]
- [[ProPgMtThreads|Threads]]
- [[ProPgMtMutualExclusion|Mutual Exclusion]]
- [[ProPgMtConditionalVariables|Conditional Variables]]
- [[ProPgMtCriticalSections|Critical Sections]]
{{fbdoc item="back" value="CatPgProgrammer|Programmer's Guide"}}


Revision [23370]

The oldest known version of this page was created on 2019-09-11 09:35:38 by fxm [new page in progress...]
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki



sf.net phatcode