Threading question

BlitzMax Forums/BlitzMax Programming/Threading question

GfK(Posted 2010) [#1]
I've started using threading to load media for my game and generally it works fine. But not always.

I have a 'loading' animation running in the main thread, and load all the assets via LoadImage, Loadsound etc, from a separate thread. As I said, most of the time this works perfectly well, but maybe once out of 50 or so times, the thread just hangs.

Due to the frequency of the bug its going to be an absolute ball ache to track down. Is there some sort of etiquette when using threads that I should know about?

I'm aware that graphics operations aren't thread-safe (apparently), but all I'm doing is loading stuff into areas of memory that are (as far as I know) not being accessed by another thread. All of the actual drawing whilst the thread is running, is done from the main thread.

There'a a bunch of threading stuff I don't understand about, like semaphores and condVars and its not very well explained in the docs, so I don't know if I should be using that or not. Also I'm only using one thread other than the main one, so do I really need a mutex? (I tried a mutex already and it made no difference, unless I did it wrong).

Any help/lowdown on correct usage of threads much appreciated.


BlitzSupport(Posted 2010) [#2]
I believe LoadImage works sometimes, but it has ties to the graphics context if I remember rightly, and that may occasionally be causing problems, since the graphics context (particularly in the case of DirectX; not too sure about OpenGL) is not thread-safe.

I'm not clear from the wording whether you mean you're calling LoadImage in the second thread, but you should be using LoadPixmap in the second thread (since a pixmap is just a block of memory, not tied to the graphics context), then calling LoadImage (loaded_pixmap) from the main thread as each pixmap loads.

... if that makes sense.


GfK(Posted 2010) [#3]
It makes sense but as I understand it, aren't images just loaded into RAM (as pixmaps) until the first time you draw them? I say this [apart from the fact that i'm sure its been said before] because its perfectly legal in Blitzmax to load all your graphics and then set a graphics mode and start drawing. So LoadImage can't possibly be tied to the graphics context in any way, can it?

But if that is the case then I'll probably drop threading completely as implementing it that way would mean a colossal amount of work. I have around 120 source files and over 20,000 lines of code.

Anyway, that aside, one thing I did note, is that my loader() function (which plays the loading animation in the main thread, and waits for the loader thread to finish), was waiting for the progress bar I have to hit 100%. The very last line in the function which loads game assets, sets the progress bar to 100%.

If I set a global variable from within a thread, is it at all possible that on occasion, the thread might end and the variable may not be set? If so, then my progress bar will never get to 100% and the whole thing will hang, as it is doing.

Anyhow, I've restructured my code on that assumption and I'll keep an eye on it for now. In the meantime I'd like a few more people's takes on this LoadImage thing.


BlitzSupport(Posted 2010) [#4]
Looks like you're right on the issue of images only being related to the graphics context when drawn -- I've just looked through TImage and DrawImage, and it looks like it's only when DrawImage calls TImage.Frame that a call to the driver is made. Apologies!


MGE(Posted 2010) [#5]
You spend a long time on a game and in the final stages try out threading? It's not worth 1/50 or 1/1000 errors. I would forget about it.

"But if that is the case then I'll probably drop threading completely as implementing it that way would mean a colossal amount of work. "

Thank you.

p.s. Yes..I'm looking forward to your game!!


Brucey(Posted 2010) [#6]
Don't you also have to assume that the relevant image loading library code is also thread-safe?
If you know for sure that it is (ie. libpng, libjpeg, etc), then time to focus attention on BlitzMax itself.


ImaginaryHuman(Posted 2010) [#7]
If you only have one background thread doing the loading and the loading code is just reading a file then I would say libjpeg has absolutely nothing to do with the problem, unless libjpeg itself has a separate problem with being in a thread... but you'd think it would be ok?

Is there absolutely nothing that the background thread accesses that the main thread might be accessing also?


Retimer(Posted 2010) [#8]
You spend a long time on a game and in the final stages try out threading? It's not worth 1/50 or 1/1000 errors. I would forget about it.


Eh, coding is boring without adding a challenge or learning experience to a project.


GfK(Posted 2010) [#9]
You spend a long time on a game and in the final stages try out threading?
Its hardly my fault if Blitzmax didn't even have threading when I started it, is it? Plus...
Eh, coding is boring without adding a challenge or learning experience to a project.
...what he said.

Is there absolutely nothing that the background thread accesses that the main thread might be accessing also?
Only the var which controls the 'progress' of the progress bar. But I've catered for that now.


_JIM(Posted 2010) [#10]
To be on the safe side you could try loading pixmaps then after the loading is done, convert them to images in the main thread.


GfK(Posted 2010) [#11]
Well, I was setting up collision layers in a thread too. Seems thats unreliable as well so I've just started taking out all the threading stuff as I can live without it.


MGE(Posted 2010) [#12]
...what he said.


Danny(Posted 2010) [#13]
Not suggesting you should re-implement threading again ;) but could perhaps your problem have anything to do with FreeImage not being thread safe?!
As spotted in this one: http://www.blitzbasic.com/Community/posts.php?topic=88923

Just a thought..

Danny.