multi-threading: what must be done in main thread?

BlitzMax Forums/BlitzMax Programming/multi-threading: what must be done in main thread?

Rozek(Posted 2010) [#1]
Hello!

If you are following the activities in this forum, you might already have realized that I am currently (heavily) struggling with multi-threading related issues...

My current problem: it seems that even "loadImage" must only be done from within the main thread (which is really difficult for me as I need the image size in my subthread)

In order not to jump from one trap to the next: is there a list of functions which must only be called from the main thread?

Thanks in advance for any hints!


Rozek(Posted 2010) [#2]
By the way:

does "loadImage" cache the images which have already been loaded?


_Skully(Posted 2010) [#3]
You probably need to pass the objects back up to the main thread so they don't get GC'd? I'm not threading yet so I can't back this up ;)


slenkar(Posted 2010) [#4]
just graphics related functions i think


ziggy(Posted 2010) [#5]
Graphic related API calls should be done from a single thread as OpenGL and DX7 are not thread safe (not sure about DX9). It does not have to be the main thread as long as there are not concurrent API calls from several threads.


marksibly(Posted 2010) [#6]
Hi,

Unfortunately, working out what needs to be on the 'main thread', what is threadsafe or not etc is all very much subject to experimentation right now.

For example, the Cocoa docs state that Cocoa is 'mostly' multi-threaded - not sure what that means exactly.

OpenGL will probably require you to use the same thread that the GL context was created in (or perhaps you can duplicate the context among threads), while 'some parts' of DirectX should only apparently be called from the main thread (SetCooperativeLevel in d3d7 I think - not sure what the situation is in d3d9).

This is part of the reason I changed your glDeleteTextures fix - by flushing GC'd textures before creating textures, you at least guarantee that textures are created/deleted by the same thread, if not necessarily the main thread.

There are no doubt plenty of other caveats with threading - one of the things I was *hopefully* clear about when adding threads to bmx was that I was not gonna even attempt to handle all these issues, although I am happy to fix things on a one-by-one basis as people find them.

I suggest you google for OpenGL threading, although it's probably not a pretty situation.


marksibly(Posted 2010) [#7]
http://hacksoflife.blogspot.com/2008/02/creating-opengl-objects-in-second.html


Rozek(Posted 2010) [#8]
Good morning!

Thanks for all your contributions!

Would it be safe to say:

- BlitzMAX internal (i.e. non-system) functions are all thread-safe
- system calls may not be thread-safe

Thread-safe are
- BASIC compatibility
- BlitzMAX runtime
- Reflection
- Lists and Maps
- Math
- Banks?
- ZLib compression
- Networking (hopefully)
- Lua
- Streams?
- File System
- Standard IO
- Thread Synchronization, of course
- perhaps Joystick?
Can somebody (Mark?) please check and/or modify this list?

Inherently unsafe are
- Audio?
- Graphics
- MaxGUI
- System module
- Polled Input

Could postEvent be made thread-safe (postevent from any thread, waitevent/peekevent/pollevent etc. only in main thread - this would prevent people like me from having to implement an additional event queue besides the built-in one for those events which are sent from other threads)? (because auf EventHooks this might mean, that enqueuing a new event and invoking all event hooks might have to be separated)

Multi-threading is such a powerful tool (especially on multi-core systems) that we should come up with more precise information as soon as possible! Personally, I would not worry too much about a list of thread-safe packages which is "conservative", i.e. which excludes functions which *might* be thread-safe but are not *definitely* known to be so - because it's more important to know, which packages are *definitely* thread-safe ON ALL PLATFORMS (as you can't have multiple program designs for several platforms)


ima747(Posted 2010) [#9]
EmitEvent is not safe to call from child threads? I very much second the request for a list of safe/unsafe elements. I've had no problems emitting events from a child thread so far, but maybe that's just luck... at one point due to a typo I was even reading events on 2 threads at once and it didn't crash, however it did spew a huge list of warnings regarding draining the event pool...


Rozek(Posted 2010) [#10]
Yes,

Mark himself told us so (see http://www.blitzmax.com/Community/posts.php?topic=88828#1022023) that's why I had to implement my own queueing sysem in order to let subthreads send events to the main thread (which does the MaxGUI stuff). While queueing itself is simple, (non-busy) waiting for both a system event AND a semaphore seems to be impossible in a general context (in *my* special application, I have a 30Hz timer anyway and, thus, I use that to periodically check the contents of my own event queue)


ima747(Posted 2010) [#11]
Interesting, I've been spawning events from a child thread without problem so far, however my event que is pretty weird and the events from the child are just requests for canvas refreshes when nothing else is happening so if they are ignored for a while it's not really noticeable... but I'm probably getting lucky on my posting times according to that thread.

Welp, time to make a second que.


Rozek(Posted 2010) [#12]
As Mark said,

"postEvent" is *almost* thread-safe - but that's common in the area of multi-threading: even an unsafe solution might work most of the time! And THAT is the basic problem: you may think to be on the safe side, but experience "strange" side-effects from time to time which are difficult to isolate.

For that reason: be *very* careful when it comes to MT and reduce inter-thread communicatoin to a minimum!