BlitzThreads (Windows only)
Community Forums/Showcase/BlitzThreads (Windows only)
| ||
Blitzthreads lets you spawn windows-driven threads(Including dynamic priority per thread) within bmax. This version is freeware. With this you can run functions side by side your main app. You can run upto 2024 threads at once(Although I wouldn't suggest it...:) ) www.excess.eclipse.co.uk/dreamspace.mod.zip It's object driven, although there are function wrappers for those used to that. Classes are(There's no docs) TThread. Global functions(Contained within TThread. I.e TThread. Create() ) Create( BlitzFunction ) Create a thread and return a TThread object. RunAll() 'Runs all threads PauseAll() 'Pauses all threads StopAll() 'Stops all threads Local functions specific to each thread instance, Run() 'Runs the function provided when creating the thread, in another thread. Priority( Value:Int) 'Set the threads priority, value ranges from 1 to 7. (default = 3, pre-set) Pause() 'Pause the thread Resume() 'Resume the thread, - Global functions within TThread to allow async data access, All return a TResource object/integer handle. ProtectInt( x variable ) ProtectFloat( x variable ) ProtectBank( Bank:TBank ) ProtectStream( Stream:TStream ) - With the tResource object returned, you can lock access rights to it within your thread, Wrapper functions are, ThreadHandle =CreateThread( Function ) PauseThread( ThreadHandle ) ThreadPriority( ThreadHandle,Priority ) PauseThread(Threadhandle) ResumeThread(ThreadHandle) StopThread(ThreadHandle) RunThread(ThreadHandle) There's also a manual locking system, in addition to protected storage. Lock = CreateLock() RequestLock(Lock) ReleaseLock(lock) which allows you to restrict threads of the same locking patterns to one run at a time.(Prevent deadlocks..if you're lucky :) ) TestApp Simple mode Update = CreateThread( UpdateVal ) NetWork = CreateThread( PrintVal ) RunThread(Update) RunThread(NetWork) Global ourVal Function updateVal:Int(bb_func:Byte Ptr) repeat ourVal:+1 forever End function Function printVal:Int (bb_func:Byte Ptr) repeat Print "Val:"+OurVal Delay 1000 forever End Function Print "Thread Handle>"+Res repeat Delay 5000 Print "Master thread!" Forever Advanced Mode Update:TThread = TThread.Create( UpdateVal ) NetWork:TThread = TThread.Create( PrintVal ) Update.Run() Network.Run() Global ourVal Function updateVal:Int(bb_func:Byte Ptr) repeat ourVal:+1 forever End function Function printVal:Int (bb_func:Byte Ptr) repeat Print "Val:"+OurVal Delay 1000 forever End Function Print "Thread Handle>"+Res repeat Delay 5000 Print "Master thread!" Forever To install, copy dreamspace.mod folder into your bmax mod folder(Windows only atm) and you're done. |
| ||
First tests work great here.. Nice work, Antony.. :) |
| ||
very nice addition to bmax. |
| ||
am I awake ? .. ok I have a few questions if you dont mind ant. 1. Can I start a thread that will play an AVI aka game into and then continue to load my game media ? 2. Can more than one thread drop stuff to the back buffer ? for example a game I did in Java, I had a "Insert Coin" that flashed on the screen, but the flash was controlled by a thread so it didnt have anything in the main loop telling it to flash. So can this be done ? Is it stable enough to put something like AI into a thread and let it mince away on some complex AI choice tree while the rest of the game runs alone as normal, think chess ? |
| ||
Thanks lars, Kanati. 1. Can I start a thread that will play an AVI aka game into and then continue to load my game media ? If you can do it in your main game, you can put it in a thread. I think the only thing on windows that doesn't like being threaded is dx stuff. Gl should be fine. 2. Can more than one thread drop stuff to the back buffer ? for example a game I did in Java, I had a "Insert Coin" that flashed on the screen, but the flash was controlled by a thread so it didnt have anything in the main loop telling it to flash. So can this be done ? Yep. Just create an endless loop in the thread. they don't have to return, whenever you call a thread it returns immediately. Is it stable enough to put something like AI into a thread and let it mince away on some complex AI choice tree while the rest of the game runs alone as normal, think chess ? Yep. In the 'next' version, you can specify which processer the thread is executed on, in theory allowing true multi-cpu possibilities. |
| ||
Nice one Ant ;) |
| ||
Great thing :) Now I can start to dream of stuff that I was not capable to create without bad headaches in the past :) |
| ||
Wow. It'd be really awesome if some linux and mac people could implement the same functions sets for those platforms, so you can use these on all platforms. |
| ||
WELL all I got left to say is BLOODY well done m8 and where the heck is the download link for it(j/k) Hay Any chance you could possibly knock up an example of it in use ? |
| ||
I got a request if thats ok. IsThreadActive:Boolean() My thoughts are like this. initgame() thread -> loadmedia() repeat until IsThreadActive()=false Playegame() if thats not clear, we need a way to check if a thread thats loading media for the game is done yet, so we know if its safe to actually start drawing or playing sounds.. would be a nightmare if on some machines the thread dosent get all the needed media loaded befre the main program gets to a draw command. |
| ||
awesome. it is win32 only? |
| ||
Nice and Impressive Antony! Is it planned to make this work crossplatform;MacOs,Linux? I haven't programmed with threads before but I can imagine what will be possible =) |
| ||
Awesome work Antony. Frikkin brilliant. I second Bot Builders request! If it's too messy to merge into one module, each platform could have a seperate thread module, so long as eventually somebody makes a fourth 'helper' module that handles all the messiness behind the scenes... |
| ||
Yavin ... your way of using it makes it useless if you wait until loading is done anyway ... you could just use the normal functionality then ;) |
| ||
Dreamora : Wrong. the example I gave was for playing an AVI Game Intro while loading the game media in the background, when the Intro AVI ends you want the game menu to start but there could be a situation where the thread loading all your media behind the avi is not yet finished, so a please wait msg could be displayed intil it is done. So like I said Ant the thread god could we get a isitrunning function. ta :) |
| ||
thread are really good, thats out of question but can't see your "runs an avi" thing ... you have an init and a thread that is loading and after loading is finished you play the game ... where is there actually the "AVI" part? thats why I meant there is not much use of this construct, sorry. |
| ||
but can't see your "runs an avi" thing ... you have an init and a thread that is loading and after loading is finished you play the game ... where is there actually the "AVI" part? thats why I meant there is not much use of this construct, sorry. Eh? I think he's just talking about the ability to play an animation *while* the necesary sprites, background, music, etc. of your game is being loaded in the background. Which would be quite useful, since it means you don't have to stare at a static screen during the loading period. |
| ||
Thanks Antony. Like Bot Builder, I'd also like to see versions for Linux and Mac. I think he's just talking about the ability to play an animation *while* the necesary sprites, background, music, etc. of your game is being loaded in the background. Yeah. Games could learn alot from that. Having 9 or 10 long animations running before the game starts, that you can't even skip past, and then once you've done that, it's "Please wait some more ... Loading". |
| ||
I got a request if thats ok. IsThreadActive:Boolean() My thoughts are like this. initgame() thread -> loadmedia() repeat until IsThreadActive()=false Playegame() The 'next' version will spawn threads within a carrier function to allow this. Sadly winAPI doesn't(or at least msdn doesn't document it) have any functions to just check if a thread is running. In the mean time, remember threads have the SAME scope as the function would if you called it normally. So for now, global MediaLoading = true function LoadMedia:Int(bb_func:Byte ptr ) 'load media MediaLoading = false end function CreateThreaad( LoadMedia) while MediaLoading wend 'wait for media to finish loading. --- it is win32 only? Is it planned to make this work crossplatform;MacOs,Linux? Win32 for now, mac/Linux versions to come. It will be totally abstracted, so anycode you write in the windows version will eventually work without alteration on other platforms, basically.. --- Btw, never mentioned it before, but if you guys find any bugs, please report them. Ant. And on the next version of Arrested Threads, Jobe smuggles himself out of prison and into solitary. "I've made a huge mistake" |
| ||
So now BlitzMax has threads, why do you ask Mark to add it if you can do it this easy ;) |
| ||
I thought it would be harder :) |
| ||
This is his finest hour, he stands among giants. The wind blasts through his heroic mane, and his steely jaw glints and reflects lensflares from the burning sun! His threading has caused the mob to hush in awe... Rome is the mob and Antony is the Queen. I mean, erm. Well done, it's great stuff - how will you do mac and linux? |
| ||
Nice stuff :) I was gonna look into this, but it looks like you have beat me! Lets hope BRL see the light. People want power! |
| ||
Ah cool Ant, I never thought of that, that will solve any problems with the thread taking longer than expected to finish. LOL and Flameduck, I think its a hell of a lot better to sit and watch some nice wee game intro than to sit looking at a static loading screen.. I mean if its a simple choice between looking at "Loading please wait ......" or some nice looking logo thing or game intro I know what one Id pick. OF course though all loading should be kept to a min to make sure the player gets into the game nice and quick. |
| ||
Flameduck, I think its a hell of a lot better to sit and watch some nice wee game intro than to sit looking at a static loading screen.. I think you misunderstand Flameduck. He's not advocating static screens over animated screens. He's advocating that loading should occur DURING the intro animation(s), not AFTER on a static loading screen. This happens far too often in commercial games and to me smacks of laziness. Oh, and well done Antony, looks good! |
| ||
Yeah your right Mark. I guess I missread that the first time. Soz flameduck and I agree with you 100%. I could name a few games as well that hit you with a loading animation and then when its done they load the game media. Well thanks to Antony and his thready goodness we wont have to bother waiting around anymore. I guess the only question is now, Whos good at making avi intros lol. |
| ||
I think the only thing on windows that doesn't like being threaded is dx stuff. Gl should be fine. OpenGL is not thread safe. Everything should be done in the same thread that created the graphics context, unfortunately. It might work on some systems, but not with others. YMMV. As a rule of thumb, I'd keep all the graphics commands in the original thread. |
| ||
I imagine there's more stuff that isn't thread safe than you would imagine. I'd be very careful with this stuff, folks. If BlitzMax doesn't have threads natively, odds are that it wasn't coded in a thread safe, re-entrant manner. Be wary. There may be weird and spooky bugs ahead. :) |
| ||
I can think of two areas where this is going to really help, the first is as I said above, getting all your media loaded while playing some movie intro at the same time to keep the gamer intrested. Then you have AI to think of, AI in games is and has always beena big bottle neck, the more complex the AI the more cpu time it takes away from your game logic/rendering time. just think how good its going to be when in your main loop, at the start of it you can just fire your AI function off in a thread and then while thats working out its next move your code can then get on with updating vars, or drawing the game to screen. The last thing I can think of and probably the first thing I will try is going to be networking. Just think for example if you want to ping a list of servers, to find out if the gameserver is still running or to find out what the ttl is. you will be able to fire off say 20 pings at once in threads at a single time instead of running through each one , one at a time. the amount of time this is going to save is .... well a lot. |
| ||
Just to be a slightly soggy blanket here ... threading isn't magic. It isn't like you're getting another processor installed in your machine or something. You're still using the same amount of processor each frame, except now you're spreading it over a wider array of tasks. Things are still going to take the same amount of time to complete (possibly more, in fact), but the main advantage is that they can move forward at the same time rather than in sequence. |
| ||
>the main advantage is that they can move forward at the same time rather than in sequence exactly, nothing will be faster, things will be proccessed in sequence and instead of thing A finishing before thing Z, now both things will finish at the same time. |
| ||
You can off-load threads onto any cpu, so if you do have a multi-cpu set up, it is like getting another processor, as according to a flameduck(I think) post blitzMax only uses one, no matter how many there are. That may be niche now..but it won't be in two years.(Not at the high end..multi-core will be the new p4. or whatever.) - But saying that, the beauty of threads to me has never been a magical means to speed up existing routines, it's been to open new doors. I just finished adding streaming support to trinity.(Load wise) so can load an entity in about 0.3 secs(On a p2-350 atm..<insert appropriate swear word>) without pausing the app. And in a real time context, reducing a 0.3 second pause per frame to no pause is a quantum leap in performace. - Skunk, lay off the..yourself. :) OpenGL is not thread safe. Everything should be done in the same thread that created the graphics context, unfortunately. It might work on some systems, but not with others. YMMV. As a rule of thumb, I'd keep all the graphics commands in the original thread. Are you sure? I've seen numerous sites specifically citing speeding up real time apps by threading the 3d engine(I.e the rendering aspect). Though it's not vital anyway, as the cpu intensive stuff is what you want to thread. |
| ||
It's responsiveness not speed that's improved - many people mistakenly mix the two. Re opengl, same thing basically and I would guess mainly offloading non rendering stuff while keeping rendering in same thread. Seperate threads for seperate context's seems a good idea? |
| ||
Are you sure? Pretty sure. OpenGL is state-based. Mess with anything out of sequence and you're screwed. Not only that, but it's been my experience that just calling an OpenGL function can cause the app to segfault. I don't know why. Do you have any links to those sites? |
| ||
Not 'on me', it was when I was reading up on threads..So could be any link on google from a "thread tutorial/ C++ Threads" search, was in the sections mentioning the benefits of threads. - About being state based, my own solution would be to objectize(ahem) state access throug a wrapper class, and precede every function with a mutex lock request on it's own personal mutex. So if two threads do attempt to change a state at once they'll be denied access.(they'll just queue up in order of request) Plus you can implement a lock/unlock method when you want to prevent any other threads from making changes. The nice thing about a mutex request is it actually stalls the thread on the request until it has the lock, so it prevents multiple threads from accessing any proceding code. I believe recent drivers also added support for child Contexts, or shared contexts, which may be a solution to any crashes caused by that.(Not tested.) |
| ||
There is stuff you can do in threads on OpenGL like buffer modifications or display list modifications but I think threading anything out of the "pipe" would totally screw the thing ... |
| ||
So now BlitzMax has threads, why do you ask Mark to add it if you can do it this easy ;) I think the better question is why hasn't Mark done this since it's so damn easy ;] There may be a very good reason... but it's -so- -much- more FUN to find out the hard way, innit? ;] Whos good at making avi intros lol. It's not too difficult to get your hands on some 'home movie' sorta software for a reasonable price. Movie Maker if you're -really- desperate (altho then you'd need another proggy to convert the wmv to avi) |
| ||
It's not too difficult to get your hands on some 'home movie' sorta software for a reasonable price. Movie Maker if you're -really- desperate (altho then you'd need another proggy to convert the wmv to avi) I use Prem 8 on the PC and some times I edit my TV or cinema trailer stuff on Mac, just recently had to submit two trailers for the movie robocop. The Hardware and software aint a problem, I was more thinking along the lines of creating the 3D intro like mby EA's or Capcoms.. something like that. |
| ||
well done, but beware.. http://home.pacbell.net/ouster/threads.pdf an older article but still relavant. |
| ||
That's a really good article. Lays it all out in plain English. |
| ||
This seems like a groovy addition, but I can't myself consider it an `addition to blitzmax` or that `blitzmax now has threads` until it is supported on all the platforms that blitzmax ports to *being purist*. But great job on the `progress` though. I also am expecting there must be some areas where, having two parts of a BlitzMax app running simultaneously is likely to not take into account some internal variables which may have no protection from being changed at the wrong time or not being locked, etc... I guess it'll almost be hit and miss as to which parts work together and which dont? Still, it's pretty cool and looking forward to seeing it on all platforms. |
| ||
Urban legends aside, I've got too much going on project wise to try and implement any sort of multi-platform. So here's the bmax/C++ source used, public domain so hopefully someone else can finish it off for us.(this won't be a commercial product from me. ever.) anyway, enough rambling, here's the juice. (This is the latest version btw, I'd nab it if you're using the above. You can now pass a pointer to a thread. (Edit-fixed a bug.) 'TheadLayer.c Freel free to upload any improvements to this thread..or your own. |
| ||
Antony, you're a great asset to this community! Thanks alot! |
| ||
Umm, Sorry to be a party pooper, but this is pretty much guaranteed to fail sooner or later. The likely result of using threads like this is that things will work fine 99% of the time, and every now and then something will mysteriously screw up. The problem is that certain runtime operations need 'locks' around them to work properly concurrently, and there is nothing like that in place. By all means, use at your own risk - but you've been warned! Threading is something I eventually want to look at, but it's not as simple as it sounds. |
| ||
Ash, thanks, I usually hear that in reverse :) Mark, locking is in place, so any modules of yours can be manually locked. Custom modules, like mine of course CAN be wrote thread safe from the start, so it's only really true of your modules anyway. Unless your compiler is generating asm which relies on any global areas that other threads could 'mess up' regardless of the modules being used? I don't see any such code in the asm produced though, though I never looked too hard. Would be helpful if you made it clearer to us what to avoid, if I've missed something. -[Edit - Or the usual stonewall of silence..whatever... |