'' examples/manual/proguide/multithreading/criticalsectionfaq1.bas
''
'' Example extracted from the FreeBASIC Manual
'' from topic 'Critical Sections FAQ'
''
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=ProPgMtCriticalSectionsFAQ
'' --------

'   - The "user-defined thread" computes the points coordinates on a circle,
'     and write those in a LongInt (32-bit & 32-bit = 64-bit)
'   - The "main thread" plots the points from the LongInt value.
'
'   Behavior:
'      - The first point must be pre-determined.
'      - Nothing prevents that a same calculated point could be plotted several times
'      (depends on execution times of the loops between main thread and user thread).
'      - Nothing prevents that a calculated point could be not plotted
'      (same remark on the loop times).
'
'   Remark:
'      Voluntarily, there is no Sleep in the loop of each thread (normally strongly discouraged),
'      but this is just in this special case to amplify the behavior effects to observe.
'
'   Threading:
'      This FAQ deliberately leaves the Point2D transfer and quit flag
'      unsynchronized. Uncommenting the adjacent MutexLock/MutexUnlock pairs is
'      the corrected variant; the visible duplicate or missed points are the
'      point of this demonstration.


Union Point2D
	Dim As LongInt xy
	Type
		Dim As Long y
		Dim As Long x
	End Type
End Union

Dim As Any Ptr handle
' The FAQ keeps the mutex and quit flag module-visible for its worker and main
' thread. Their deliberately unsynchronized accesses are documented above.
'' FB-LINTER: DISABLE-NEXT-LINE FBL301
Dim Shared As Any Ptr mutex
Dim Shared As Integer quit

Sub Thread (ByVal param As Any Ptr)
	Const pi As Single = 4 * Atn(1)
	Dim As Point2D Ptr p = param
	Do
		Dim As Point2D P2D0
		Dim As Single teta = 2 * pi * Rnd
		P2D0.x = 320 + 200 * Cos(teta)
		P2D0.y = 240 + 200 * Sin(teta)
'        Mutexlock(mutex)
		p->xy = P2D0.xy
'        Mutexunlock(mutex)
'        Sleep 5, 1
	Loop Until quit = 1
End Sub


Screen 12
Randomize Timer

Dim As Point2D P2D
P2D.x = 520
P2D.y = 240

mutex = MutexCreate
handle = ThreadCreate(@Thread, @P2D)

Dim As Integer c

Do
	Dim As Point2D P2D0
'    Mutexlock(mutex)
	P2D0.xy = P2D.xy
'    Mutexunlock(mutex)
	PSet (P2D0.x, P2D0.y), c
	c = (c Mod 15) + 1
'    Sleep 5, 1
Loop Until Inkey <> ""

quit = 1
ThreadWait(handle)
MutexDestroy(mutex)
