Blitzmax threading examples thread

BlitzMax Forums/BlitzMax Programming/Blitzmax threading examples thread

skn3(Posted 2008) [#1]
Thought it might be a good idea to create a thread to post threading examples for those who want to pick up how it all works. So here goes :)

I am learning this too, so if I have got anything wrong please correct me.


skn3(Posted 2008) [#2]
Example: WaitCond, SignalCond, LockMutex, UnlockMutex

This examples demonstrates creating a thread and putting it to sleep. The main thread will then signal to the thread at a certain point that it wants to reawaken.

Global cond_mutex:Int = CreateMutex()
Global cond:Int = CreateCond()
Global mutex_print:Int = CreateMutex()

'create a thread that points to threadfunc as its runtime
Local thread:Int = CreateThread(threadfunc,Null)

Local temp:Int

'start our main thread runtime
'this will just wait for teh user to press space and then end
Graphics 640,480,0,60
Repeat
	Cls
		DrawText("Press space to signal the thread to start",5,5)
		
		'the thread has locked the mutex, but as it is asleep we are still able to...
		'lock the mutex successfully
		temp = TryLockMutex(cond_mutex)
		DrawText("Locking mutex now = "+temp,5,25)
		If temp UnlockMutex(cond_mutex)
	Flip
Until KeyHit(KEY_SPACE)
EndGraphics

'signal the thread to wakeup
SignalCond(cond)

'wait for the thread to end
WaitThread(thread)

'close the thread
DetachThread(thread)



Function threadfunc:Object(nobject:Object)
	'this thread will wait (without using up system recources) until ...
	'it has been signaled by the main thread To wakeup
	
	'lock the mutex used with the wait condition
	LockMutex(cond_mutex)
	
	'put this thread to sleep until it recieves a signal, the mutex will be available...
	'while the thread is asleep
	WaitCond(cond,cond_mutex)
	
	'upon wakeup do something interesting
	tPrint "I am a thread and I have been signaled to start..."
	For Local index:Int = 1 To 10
		tPrint "thread is counting: "+index
	Next
	
	'release the mutex
	UnlockMutex(cond_mutex)
End Function

Function tprint(ntext:String)
	LockMutex(mutex_print)
	Print(ntext)
	UnlockMutex(mutex_print)
End Function



skn3(Posted 2008) [#3]
Example: LockMutex, UnlockMutex, Creating multiple threads, Waiting for threads to end, Thread safe blitzmax function

This example will create a mass of threads that all print to the console. When the main thread decides its time to finish, it will wait for all the threads to finish by keeping a count of the number of threads that have finished.

Const total_background_threads:Int = 10

Global program_ending:Int = False
Global closed_threads:Int = 0

Local threads:Int[total_background_threads]

Local index:Int = 0
For index = 0 Until total_background_threads
	threads[index] = CreateThread(threadfunc,String(index))
Next

' - main thread runtime here
Graphics 640,480,0,60
Local count:Int = 0
Local value:Float = 0
Local size:Float = 0
Repeat
	Cls
	count:+1
	value = Abs(Cos(count))
	size = (value * 200) + 100
	SetColor((155.0*value)+100,100.0*value,100.0*value)
	DrawOval(MouseX()-(size/2),MouseY()-(size/2),size,size)
	SetColor(0,255,0)
	DrawText("Press esc to end",5,5)
	Flip
Until KeyDown(KEY_ESCAPE) = True
EndGraphics


' - terminate the background threads
'close all the thread handles
tprint  "*** closing threads"
program_ending = True
For index = 0 Until total_background_threads
	DetachThread(threads[index])
Next
'wait until all threads have closed
Repeat
	Delay 10
Until closed_threads = total_background_threads


' - thread functions
'background thread, this is the 2nd thread in the program
Function threadfunc:Object(nobject:Object)
	'pause for a bit before printing
	Local count:Int = 0
	Local timedelay:Int = Rand(200,2000)
	While program_ending = False
		Delay timedelay
		count:+1
		If program_ending = False tprint "background thread "+String(nobject)+" (call: "+count+")"
	Wend
	
	'increase closed thread count and display message
	closed_threads:+1
	tprint "closing background thread "+String(nobject)
End Function

'threaded print command, this will allow you to safely print within threads
Function tprint(ntext:String)
	'this will create a speciffic mutex for locking the print command to reuse every function call
	Global mutex:Int = CreateMutex()
	
	'lock the mutex
	'this function will ask the system "can i please lock the mutex", as the mutex can only have two states:
	' - locked
	' - unlocked
	'like a 'bit' (0 or 1), it means that only one thing can be in control of the mutex. The function will 
	'wait in line until the system says it can lock the mutex. It is important to no keep the mutex locked in a perminant
	'loop, especialy for a print command, as it is a regualrly used function.
	
	'if you try and lock the mutex, but it is already locked, it means another thread is currently printing something.
	'Once the print has completed and the mutex is unlocked, any calls to print during, will go through one by one until there
	'are no more attempts to locked the mutex and print.
	LockMutex(mutex)
	Print ntext
	
	'we have finished our printing so unlock the mutex so that other threads may use it
	UnlockMutex(mutex)
End Function



plash(Posted 2008) [#4]
http://blitzbasic.com/Community/posts.php?topic=80677


skn3(Posted 2008) [#5]
Ahh I did not know we had a tutorials forum :)

Well maybe this thread can stand as a place for more and more examples as people play around with it all.


GfK(Posted 2008) [#6]
What's a mutex?


plash(Posted 2008) [#7]
Ahh I did not know we had a tutorials forum :)
I wasn't hinting that, just thought I would add it to the list (imo this sort of thing is better here, as it can be more freely discussed.)


Brucey(Posted 2008) [#8]
What's a mutex?

It's an abreviation for MUTual EXclusion.

Basically it means, only one at a time :-)


skn3(Posted 2008) [#9]
A mutex is basically a way to say "THIS IS MYN NO ONE ELSE CAN HAVE IT!".

If you image a mutex to be a small pebble. Everyone wants the pebble, but only one person can hold it at a time. Everyone else wanting the pebble has to wait in line. When the person holding the pebble drops it, the next person in line picks it up.

Example:
Global counter_mutex = CreateMutex()
Global myvalue:Int = 10

Function increase_multiply(namount)
	LockMutex(mutex)
	myvalue = myvalue * namount
	UnlockMutex(mutex)
End Function


If you imagine that 10 threads are running, and they are all trying to use the function at the same time. They would all be trying to access the global variable at the same time. By locking the mutex any other attempts to lockmutex will wait in a queue until it has been unlocked.

The function LockMutex halts the thread at that line of code until the system says its your turn to hold the pebble.