Making a callback thread safe

BlitzMax Forums/BlitzMax Programming/Making a callback thread safe

JoshK(Posted 2008) [#1]
I am working with a multi-threaded physics library that uses callbacks during the physics update routine. GCSuspend() is called before the physics update, and GCResume() is called after.

The callbacks use the "c" calling convention. With a single core the program runs perfectly. A crash results when the physics use more than one thread. How can I make the callbacks thread-safe? As I understand it, all the function variables are "up for grabs" at any time. Each callback has a parameter indicating which thread is in use. So would I do something like this?:

Current code:
Function Callback( threadIndex:Int ) "C"
Local a:Int
a = 3
EndFunction


Thread-safe code:
Function Callback( threadIndex:Int ) "C"
Local a:Int[ 2 ]
a[ threadindex ] = 3
EndFunction



Who was John Galt?(Posted 2008) [#2]
I don't think it's possible, TBH. What error is Blitz throwing?

I had a problem with an FMOD callback a while ago. Kept throwing a 'scope stack underflow' and no-one seemed able to come up with a solution, even BRL.


JoshK(Posted 2008) [#3]
I am not using objects or doing anything crazy. Just using some local variables. If I write to anything global, I lock the threads while writing.

Local variables should be fine, right? Those should not interfere with each other on separate threads.


Who was John Galt?(Posted 2008) [#4]
Sorry mate, I'm not totally sure, but I can't see how local variables could cause a problem. I do know that I tried removing anything that I thought could create garbage from my callback and did the nogc thing and I was still getting errors. How are you locking the threads? This one REALLY needs a response from BRL.


REDi(Posted 2008) [#5]
Try this mate... (no promises)
Function Callback( threadIndex:Int ) "C" NoDebug
Global a:Int[ 2 ]
a[ threadindex ] = 3
EndFunction

IMHO thats about as safe as it gets ATM, if that still causes problems then you could try adding a critical section.

but if you're only going to be doing a bit of math in the callback I'd suggest writing it in C.


JoshK(Posted 2008) [#6]
Local variables should not need to be protected like that in an array.

Does NoDebug have any effect when the code is compiled in release mode?


Mark Tiffany(Posted 2008) [#7]
Does NoDebug have any effect when the code is compiled in release mode?

No. Why would you expect it to?

The point of NoDebug is to turn off *debugging* in a given function, e.g. something you call many times per loop that you know works and want to avoid the performance hit in debug. (I think it's also used in the blitzmax source a bit too).


JoshK(Posted 2008) [#8]
I don't. It did not make sense that this was suggested as a solution to the problem.


skidracer(Posted 2008) [#9]
Josh, the only solution is to code the callback in C, there is some sync functions available if you look in brl.system for the callback to communicate with your blitz app but I would look at a simple PostMessage type solution first. You can NOT use BlitzMax functions in the context of other threads.


JoshK(Posted 2008) [#10]
Thank you for the information.


REDi(Posted 2008) [#11]
It did not make sense that this was suggested as a solution to the problem.

of course it does but only when you run in debug mode, as debug mode adds a load of stuff to your code to track whats going on, stuff that would probably mess up threading.

The main change was to *try* it with a global array, so the GC wouldnt get involved, as you used a local array in your original attempt that would have to be created and GCed every time the function was called.

anyway I assume it didnt work, so its time to crack out a bit of C ;)