How to create threads in window

BlitzMax Forums/BlitzMax Programming/How to create threads in window

nikolai(Posted 2005) [#1]
I found a way how to create thread in windows:
======== thread.bmx File 1 of 2 =============
Strict 
Import "win32thread.bmx"
Global count:Int  = 0

Local funcPtr:Int() = foo
Local funcPtr2:Int() = foo2

Local h1:Int = CreateThread(Null,0,funcPtr)				
Local h2:Int = CreateThread(Null, 0,funcPtr2)
					
While True
	If count = 10 
		TerminateThread(h1)
		Print ""
		Print "Thread 1 terminates..."
		Print ""
		count = 0
	End If
Wend 


Function foo()
	While True
		Print "Thread Nr. 1 counts: "  + count
		count = count + 1
		Delay 750
	Wend
End Function 	

Function foo2()
	While True
		Print "Hallo, I'm thread number 2"
		Delay 500
	Wend
End Function 				
				

======= win32thread.bmx File 2 of 2 =======
Extern "Win32"
	
	Rem	
		The CreateThread function creates a thread to execute within 
		the virtual address space of the calling process.
				
		HANDLE CreateThread(
		  LPSECURITY_ATTRIBUTES lpThreadAttributes,
		  SIZE_T dwStackSize,
		  LPTHREAD_START_ROUTINE lpStartAddress,
		  LPVOID lpParameter,
		  DWORD dwCreationFlags,
		  LPDWORD lpThreadId
		);			
		
		Return Values
			If the function succeeds, the return value is a handle to the new thread.

			If the function fails, the return value is NULL.
	End Rem 

	Function CreateThread:Int (lpThreadAttributes:Byte Ptr,.. 'Pointer to a SECURITY_ATTRIBUTES structure. 
									dwStackSize:Int,.. 'Initial size of the stack, in bytes.
									pStartAddress:Int(), .. 'Pointer To the application-defined Function To be executed by the thread And represents the starting address of the thread. 
									lpParameter:Byte Ptr=Null,.. ' Pointer to a variable to be passed to the thread.
									dwCreationFlags:Int=0,.. 'Flags that control the creation of the thread. 
									pThreadId:Int Ptr=Null) 'Pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned.
	
	
	Rem	
		The TerminateThread function terminates a thread.
		
		BOOL TerminateThread(
		  HANDLE hThread,
		  DWORD dwExitCode
		);
		
		hThread
		    [in, out] Handle to the thread to terminate.
		dwExitCode
		    [in] Exit code for the thread. Use the GetExitCodeThread function 
			to retrieve a thread's exit value. 
		
		Return Values
			If the function succeeds, the return value is nonzero.
	End Rem
	Function TerminateThread:Int (hThread:Int, dwExitCode:Int =0)

End Extern



Chris C(Posted 2005) [#2]
eek! is that safe...

I wouldn't run any gui command in a thread for instance...

But I wonder if a loader could fill a bank byte at a
time while incrementing a counter, while the main app
moved a progress bar...

nice work btw!


nikolai(Posted 2005) [#3]
Another example, manipulates GUI.
You need win32thread.bmx, from first post.

=== threadGUI.bmx, File 1 of 1 ===========
Strict
Import "win32thread.bmx"

Global count = 0
Local window:TGadget
Global button:TGadget

window=CreateWindow("MaxGui Buttons",40,40,240,300,0,WINDOW_TITLEBAR)
CreateTimer(1)
button=CreateButton("Push Button",10,10,140,24,window,BUTTON_PUSH)
Local funcPtr:Int() = changeGUI
CreateThread(Null, 0, funcPtr)


While True
	WaitEvent 
	Select EventID()
		Case EVENT_WINDOWCLOSE
			End
		Case EVENT_GADGETACTION
			Print "EVENT_GADGETACTION"
	End Select
Wend


Function changeGUI()
	While True 
		count = count  + 1
		SetGadgetText button, count
		Print count 
		Delay 250
	Wend 
End Function 



Chris C(Posted 2005) [#4]
are you *sure* maxGui is thread safe!


ImaginaryHuman(Posted 2005) [#5]
you dont necessarily need hardware threads to have the appearance that more than one thing is happening at once in your program. You can implement a form of multitasking.


DStastny(Posted 2005) [#6]
Although this might appear to work. I dont think the Garbage Collector in MAX is thread safe. All my testing prior to 1.12 indicates no way to write any useful threading in BMAX. Now maybe Mark can clarify if the memory managment changes have introduced thread safe functionality. I dont see it in the source but thats not to say the compiler isnt emitting it Mutexes to make it work.

As for why this works: The method setGadetText ultimatly fails down to a windows API SendMessage to the control. And just to note the Windows GUI api is thread safe. StdIO is also thread safe which is why the print works.

Still on the fence on BMAXs ability to write threaded code... Maybe Mark can answer about the BMAX memory manager.

Doug Stastny


Hotcakes(Posted 2005) [#7]
Well according to his latest/2nd latest worklog he has been thinking about threads (altho that's about the extent of it so far I think) - which could indicate the gc revamp has been given a thread-safe approach... I guess the best way to find out (apart from a direct answer from Mark) would be to try things and see if they brake =]


jp22(Posted 2008) [#8]
Can someone tell me if this is actually safe or not?

All(!) I want is a seperate interrupt which sits there, happily updating something (think C64 IRQ's here).. Not having this ability at present really limits Max.

If it's not safe, does anyone have any suggestions, other than going the Visual C route?

Thanks


tonyg(Posted 2008) [#9]
Can you use CreateProcess?


jp22(Posted 2008) [#10]
I'm not sure that's the same thing?
From my understanding, CreateProcess will run another application. I want a method to allow another thread to run some code, where it will sit and wait in a tight loop for a semaphore or timer before processing..

Or have I missunderstood?


tonyg(Posted 2008) [#11]
I don't know as I don't know what the 'something' is you want updated.
As for CreateProcess :

I want a method to allow another thread to run some code,

OK, it's not a thread but it can run some code.
where it will sit and wait in a tight loop for a semaphore or timer before processing..

It can sit and wait on a timer or until it receives a message or data.


jp22(Posted 2008) [#12]
OK, perhaps I wasn't that clear!

What I wanted was a method to allow for an audio update routine to be updated as a background task. The update routine would handle resampling / mixing, before passing the data to a ring buffer for actual playback via the winmm waveOut functions.

All pretty simple and basic functionality - as long as I could get another thread active, which would update my audio code.

The main point is that the code at the start of this post *should* do this, but the question as to if it is safe or not was never answered from 2 years ago. So, the question remains - is using CreateThread in this manner safe or not?

My gut feeling is that its not safe, otherwise i'd also have expected some nice snazzy multi-thread commands to be added to BlitzMax. Just would really like some clafication.

Thanks
JP


Brucey(Posted 2008) [#13]
You could run other code in a different thread no problems, as long as it wasn't BlitzMax code - so something like c/c++ etc would work fine.

But if you wanted that code to call back into BlitzMax and have it do something while your BlitzMax code was already busy doing something else, there's a good chance you might get some problems cropping up.


jp22(Posted 2008) [#14]
Hmm. Thats what I thought..Shame though...I hoped to use BlitzMax for something a little more than it being essentially just a host for a bunch of DLL's.

Out of interest, what problems "might" crop up and why? Is there anything I could do to limit the risk? For example, something like only using local variables in the hope that they're just chucked on the a stack, rather than corrupting RAM? Or would I still eventually be heading towards another brick wall?

Thanks, Brucey.


REDi(Posted 2008) [#15]
According to Skidracer threads are not safe to use with the blitzmax language at all, so you have three options...

1. Do it all in blitzmax without threads (using a timer and hook).
2. Write the entire audio side in C or C++ and extern to the functionality from bmax.
3. Dump bmax and do it all in a different language (C/C++ etc or even PureBasic allows threads).

Option 1 you could use winmm+timer+hook, or you could use MaxMod and a custom TMusic object (directsound and openal support), both will have latency issues.

Option 2 is what I've ended up using for my DJ application, and I'm also having to rewrite MaxMod and my Tracker project also, but it is less cpu intensive, very low latency and for some reason sounds better :/
and as a nice side effect adding VST support is made 100% easier.

If this is just for a game I'd take option 1, but if you're doing something more audiophile related then option 2 or 3 is the best way to go (as I've found out after YEARS of trial and error).

*EDITED*


jp22(Posted 2008) [#16]
Option 2 it is then.

Thanks for the response, REDi.

JP


Ian Thompson(Posted 2008) [#17]
FreeBasic also had thread support.

It would be nice to be able to use threads in BM though :(