[Question] Multi-threading in Database Implementation
by St. · in Torque Game Engine Advanced · 04/05/2009 (5:24 am) · 5 replies
Hello.
I am trying to learn multi-threading in TGEA and was experimenting with several things. More precisely, I am hoping to implement database support that would use a separate thread (idea inspired by the "Event Driven Database" topic by Tony Richards).
I've implemented a basic database interface similar to the one provided by Tony Richards, but I've got a few questions left. As I said, I'm just learning. :)
1) Is there any way to test new thread creation? How can I make sure that a separate thread has been launched and running?
2) As I understood the following line actually creates a separate thread for the database interface class:
3) If I call any functions from my db interface class, would that mean that I am automatically referring to the second thread that was created or do I have to add any other functionality for that?
I know that my questions seem a bit "newbish", it's just the MT implementation I've seen is very different from all MT tutorials that I learned from. And I don't want to make a mess from Torque's source. :)
I am trying to learn multi-threading in TGEA and was experimenting with several things. More precisely, I am hoping to implement database support that would use a separate thread (idea inspired by the "Event Driven Database" topic by Tony Richards).
I've implemented a basic database interface similar to the one provided by Tony Richards, but I've got a few questions left. As I said, I'm just learning. :)
1) Is there any way to test new thread creation? How can I make sure that a separate thread has been launched and running?
2) As I understood the following line actually creates a separate thread for the database interface class:
m_ProcessThread = new Thread((ThreadRunFunction)processThread, this, 1);In the Tony's code the new thread is never started or stopped by calling the relevant functions (start()/stop()), does the above mentioned line start it? Or am I missing a part or two?
3) If I call any functions from my db interface class, would that mean that I am automatically referring to the second thread that was created or do I have to add any other functionality for that?
I know that my questions seem a bit "newbish", it's just the MT implementation I've seen is very different from all MT tutorials that I learned from. And I don't want to make a mess from Torque's source. :)
About the author
#2
Thanks, I have something to think about now.
P.S. As about the first question, I just didn't know how to inspect threads using debuggers. *blushes* Any information on that matter is highly appreciated. :)
04/05/2009 (7:04 am)
Hmm... I think I'm beginning to get the idea. So the only thing using the separate thread in the database interface is the "processLoop" method, everything else is still using the main one.Thanks, I have something to think about now.
P.S. As about the first question, I just didn't know how to inspect threads using debuggers. *blushes* Any information on that matter is highly appreciated. :)
#3
The third paramter, start_thread indicates if you want the thread to go ahead and start or if you want to start it manually. The default is true, which means that the thread starts as soon as you create the Thread object.
Note: I've just updated the resource to be compatible with TGEA 1.8.x. The new resource is located here
The complexity of the original resource was reduced thanks to the fact that TGEA 1.8.x now supports script callbacks from threads other than the main thread. This allowed me to simply call executef from the database thread. Torque correctly schedules the script callback execution during the next frame using the main thread. Nifty, eh?
04/05/2009 (8:32 am)
The Thread class constructors actually has two additional parameters that have default values:Thread(ThreadRunFunction func = 0, void *arg = 0, bool start_thread = true, bool autodelete = false);
The third paramter, start_thread indicates if you want the thread to go ahead and start or if you want to start it manually. The default is true, which means that the thread starts as soon as you create the Thread object.
Note: I've just updated the resource to be compatible with TGEA 1.8.x. The new resource is located here
The complexity of the original resource was reduced thanks to the fact that TGEA 1.8.x now supports script callbacks from threads other than the main thread. This allowed me to simply call executef from the database thread. Torque correctly schedules the script callback execution during the next frame using the main thread. Nifty, eh?
#4
If you're using Visual Studio, then when executing an app in the debugger you should see some tabs at the bottom, Autos, Locals, Threads, etc... the Threads tab will give you a window showing the threads in the application. If you don't see that tab/window then you can get to it by going to the Debug menu, Windows sub menu, then selecting Threads.
You'll have to be broken into the debugger to see them, so either set a breakpoint or select Break All from the Debug menu.
You'll see the threads listed with category, name, and the location that they're currently stopped at. There should be one thread with "Main Thread" category, which is the primary application thread, and a number of "Worker Threads", and possibly some "RPC Threads". When you start a new thread it will usually be a Worker Thread.
Usually a thread started from the torque Thread class will have the name "_threadstartex", and you can double click on it to "switch" to that thread, then look at the call stack to see how it originated, and usually pinpoint the thread you're looking for that way. i.e. to find the database interface thread, you'd look for DatabaseInterface::processLoop in the call stack.
Cheers
04/05/2009 (9:15 am)
@St,If you're using Visual Studio, then when executing an app in the debugger you should see some tabs at the bottom, Autos, Locals, Threads, etc... the Threads tab will give you a window showing the threads in the application. If you don't see that tab/window then you can get to it by going to the Debug menu, Windows sub menu, then selecting Threads.
You'll have to be broken into the debugger to see them, so either set a breakpoint or select Break All from the Debug menu.
You'll see the threads listed with category, name, and the location that they're currently stopped at. There should be one thread with "Main Thread" category, which is the primary application thread, and a number of "Worker Threads", and possibly some "RPC Threads". When you start a new thread it will usually be a Worker Thread.
Usually a thread started from the torque Thread class will have the name "_threadstartex", and you can double click on it to "switch" to that thread, then look at the call stack to see how it originated, and usually pinpoint the thread you're looking for that way. i.e. to find the database interface thread, you'd look for DatabaseInterface::processLoop in the call stack.
Cheers
#5
I feel ashamed for not noticing the start_thread parameter in the Thread's constructor, it looks really obvious. I guess I must have some sleep... :)
And thanks for the link Tony, I'll gladly take a look at the new resource. ;)
Once again I proved for myself that Torque's community is the most helpful community of all. It's just awesome. :)
04/05/2009 (1:17 pm)
Thank you very much, that helped a lot!I feel ashamed for not noticing the start_thread parameter in the Thread's constructor, it looks really obvious. I guess I must have some sleep... :)
And thanks for the link Tony, I'll gladly take a look at the new resource. ;)
Once again I proved for myself that Torque's community is the most helpful community of all. It's just awesome. :)
Torque Owner Gerald Fishel
Development Ninja
1) Not quite sure what you mean, but most debuggers allow you to inspect threads, so you could use that if you need independent validation that a new thread has been created.
2) start is called in the Thread class constructor, and stop is called in the Thread class destructor, so there's no need to call them separately.
3) It looks like the new thread is executing the "processLoop" method, which processes an event queue that consists of DatabaseRequest instances. So the way you'd use the interface is to post a DatabaseRequest with the postEvent method, which will add the request to the event queue and return immediately. The event will then be processed in the other thread. The specific requests are handled in processEvent, which will still be running in the database interface thread, and any further action that is needed will be posted as an event to the Game interface from there.