Now that we have threading in the experimental svn version of BlitzMAX, I've been trying to wrap my head around it. So I thought I'd start a thread for the purpose of learning.
Some functions are self explanatory, but others I can't seem to figure out.
I understand CreateThread(Entry:Object(data:Object),data:Object)
Entry is the function that is to run in it's own thread. data is an Object that will be passed to that function.
Now I'm not completely sure how to use DetatchThread() and WaitThread(). I'm assuming that when WaitThread() is called, that the main thread waits until the second thread is through, then the second thread is closed. So does DetatchThread() simply flag the GC to close the thread and allow the main thread to continue running alongside the second thread or does it immediately terminate the second thread?
When I run this example with WaitThread(), it behaves the way I expect it to
But if I replace WaitThread() with DetachThread(), The WaitOnMe() function doesn't get called and Input acts as though I already hit Enter even though I haven't touched any key.
Putting DetachThread() after the Input() and it works fine. The thread even interlaces it's Print with the main program's Print, like so, "I have waited 0 milliseIn the WcaitOonMe nThrdeads" proving that the threads are running independantly.
So am I right to assume that DetachThread() immediately ends the second thread?
Now for the data:Object parameter. Is that only for reading or can you write to it as well? This experiment seems to indicate that it can be written to, making it an ideal way for threads to pass information to each other.
I'm not completely sure if that is the correct way. It might work ok in some circumstances, but be unstable in others. As I understand it, Mutex is suppose to make shared data thread safe, but how do I use it? Do I call LockMutex() before writing to anything that is shared and UnlockMutex() afterwards? Do I need to make CreateMutex() global to the entire program or can I create a seperate mutex for every thread that uses a shared resource?
Seems that this works ok:
Is this a more appropriate way of doing it?
Also, the Entry:Object(data:Object) function returns an Object. Just what uses this object and what exactly should be returned in it?
Is this what gets returned in WaitThread()?
Some functions are self explanatory, but others I can't seem to figure out.
I understand CreateThread(Entry:Object(data:Object),data:Object)
Entry is the function that is to run in it's own thread. data is an Object that will be passed to that function.
Now I'm not completely sure how to use DetatchThread() and WaitThread(). I'm assuming that when WaitThread() is called, that the main thread waits until the second thread is through, then the second thread is closed. So does DetatchThread() simply flag the GC to close the thread and allow the main thread to continue running alongside the second thread or does it immediately terminate the second thread?
When I run this example with WaitThread(), it behaves the way I expect it to
SuperStrict Import pub.threads Local Time:Int = MilliSecs() Local Thread:Int = CreateThread(WaitOnMe,Null) WaitThread(Thread) Print "I have waited "+(MilliSecs()-Time)+" milliseconds" Input() Function WaitOnMe:Object(data:Object) Print "In the WaitOnMe Thread" Delay(10000) Print "Finished Delay" End Function
But if I replace WaitThread() with DetachThread(), The WaitOnMe() function doesn't get called and Input acts as though I already hit Enter even though I haven't touched any key.
Putting DetachThread() after the Input() and it works fine. The thread even interlaces it's Print with the main program's Print, like so, "I have waited 0 milliseIn the WcaitOonMe nThrdeads" proving that the threads are running independantly.
So am I right to assume that DetachThread() immediately ends the second thread?
Now for the data:Object parameter. Is that only for reading or can you write to it as well? This experiment seems to indicate that it can be written to, making it an ideal way for threads to pass information to each other.
SuperStrict Import pub.threads Const ThreadWait:Int = 0 Const ThreadSync:Int = 1 Const ThreadEnd:Int = -1 Type TSync Field Go:Int = ThreadWait Field Count:Int = 0 End Type Local Time:Int = MilliSecs() Local Sync:TSync = New TSync Local Thread:Int = CreateThread(WaitOnMe,Sync) Print "Beginning..." Repeat If Sync.Go = ThreadSync Print "Syncing... "+Sync.Count Sync.Go = ThreadWait End If Until Sync.Go = ThreadEnd Print "Ending..." DetachThread(Thread) Function WaitOnMe:Object(data:Object) Local Sync:TSync = TSync(data) Local Timer:Int = MilliSecs() + 1000 Repeat If MilliSecs() >= Timer Timer :+ 1000 Sync.Count :+ 1 Sync.Go = ThreadSync End If Until Sync.Count = 10 Sync.Go = ThreadEnd End Function
I'm not completely sure if that is the correct way. It might work ok in some circumstances, but be unstable in others. As I understand it, Mutex is suppose to make shared data thread safe, but how do I use it? Do I call LockMutex() before writing to anything that is shared and UnlockMutex() afterwards? Do I need to make CreateMutex() global to the entire program or can I create a seperate mutex for every thread that uses a shared resource?
Seems that this works ok:
SuperStrict Import pub.threads Const ThreadWait:Int = 0 Const ThreadSync:Int = 1 Const ThreadEnd:Int = -1 Type TSync Field Go:Int = ThreadWait Field Count:Int = 0 End Type Global Mutex:Int = CreateMutex() Local Time:Int = MilliSecs() Local Sync:TSync = New TSync Local Thread:Int = CreateThread(WaitOnMe,Sync) Print "Beginning..." Repeat If Sync.Go = ThreadSync Print "Syncing... "+Sync.Count LockMutex(Mutex) Sync.Go = ThreadWait UnlockMutex(Mutex) End If Until Sync.Go = ThreadEnd Print "Ending..." DetachThread(Thread) CloseMutex() Function WaitOnMe:Object(data:Object) Local Sync:TSync = TSync(data) Local Timer:Int = MilliSecs() + 1000 Repeat If MilliSecs() >= Timer Timer :+ 1000 LockMutex(Mutex) Sync.Count :+ 1 Sync.Go = ThreadSync UnlockMutex(Mutex) End If Until Sync.Count = 10 LockMutex(Mutex) Sync.Go = ThreadEnd UnlockMutex(Mutex) End Function
Is this a more appropriate way of doing it?
Also, the Entry:Object(data:Object) function returns an Object. Just what uses this object and what exactly should be returned in it?
Is this what gets returned in WaitThread()?