Game Development Community

Multithreading

by Mak Andrew · in Torque Game Engine · 01/18/2005 (4:39 pm) · 27 replies

Hi,

Currently, i'm trying to create a separated thread to pull data from the database(using MySQL) and then update the object pos in torque engine

In the separate thread, i have a loop that pull data from the database. For the first few loop, every things is just fine, however as the loop process, the pulling of data fail. However when i do these in single thread, the engine works perfectly.

i realise that there's a class "Thread", that do multithreading
HELP???!!!
Page «Previous 1 2
#1
01/18/2005 (10:44 pm)
Torque is not multithread safe. The threading support is only useful for very specific situations; if you don't have familiarity with multithreaded development you probably don't want to be messing with this.
#2
01/19/2005 (8:17 am)
Mak,

If you still want to try to do this multithreaded. The easiest way to jump into this would be to have a SimGroup of classes that would contain an obj id, and the new position. The background thread would obtain a Mutex (look it up on Google) to assert ownership of the list and add the updates. Then it would release it. Then you can signal the forground thread with an Event (should be covered with the mutex). The foreground thread would then obtain the mutex, read from the list, update the objects, then release the mutex.

Then you would just keep repeating this process. There are other methods of making this work, but this is the simplest that I can think of. The whole idea is that you only want one thread updating the object positions at a time. You can't guarantee that without a sychnronization technique of some sort.
#3
01/19/2005 (12:47 pm)
Bear in mind that Torque's memory manage is not thread safe, nor is the profiler, nor is the string table. ANY code you call from your thread you will have to audit to make sure you won't collide with other threads.

It might make more sense to use the HTTP code to pass events back and forth, rather than try to get threading in. A little more overhead, a LOT less work.

Incidentally, we do plan to make Torque more thread-friendly at some point in the future. Don't hold your breath, though. :)
#4
01/19/2005 (4:31 pm)
In fact, i'm able to get the multithreading stuffs only to see torque crash in the profiler...and just wondering if there's a way to conquer it.

Anyway thank for the help guys
#5
01/19/2005 (10:37 pm)
Sure, have it only profile the main thread.
#6
01/20/2005 (1:33 am)
I feel compelled to second what Ben said; don't go down the multi-threaded route unless you know what you're doing e.g. been doing such things for years and secondly, you've got a damn good reason to.

I can't go into the details but I've been heavily involved in rewriting major portions of the TGE for another project so that they become thread-safe and in the end, the benefit didn't justify the work involved. I would probably have been better off fragmenting the threads using events and/or micro-code. At this point, merging would be hell on earth.

In the end, it's easy to do if you only touch your own constructions and not call into the TGE codebase but be careful to make sure that the TGE memory-manager is thread-safe, at least.

Don't go there.

- Melv.
#7
01/20/2005 (5:32 am)
The TGE memory-manager is NOT thread safe.
#8
01/20/2005 (5:38 am)
@Pat: Was that to me? I was trying to say make sure you make it thread-safe, not check! If not, ignore everything I said. ;)
#9
01/20/2005 (6:14 am)
Damn theres some smart folks in this thread. I wouldn't dare touch this stuff and you guys talk about it like your ordering your breakfast, lol.


This class gets an A+

: O
#10
01/20/2005 (6:40 am)
@Gonzo:
Multithreading is not so hard to program. Only things that makes it hard in this case is that Mak wants a HUGE singlethreaded application (Torque) to suddenly become multithreaded. So he has two options. Either edit every function and method in the SDK or make the new threads never have access to the same pieces of memory that the rest of TGE uses ("only touch your own constructions and not call into the TGE codebase" as Melv said). If the topic interests you, try googling c++ mutex tutorial. You can easily become an expert in c++ multithreading over a weekend.
#11
01/20/2005 (6:49 am)
@Eric:
Quote:You can easily become an expert in c++ multithreading over a weekend.

Whilst I share your view that you can understand most of the concepts in a weekend, understanding all the problems associated with such coding as well as the debugging issues can take an awful lot longer. Not all texts discuss how easy it is to slip and create race-conditions, dead-locks, compiler optimisation problems (volatility) etc. Not necessarily saying that you're incorrect here, it's just that it's amazing how many things just "crop up" when doing multi-threaded code. You've got to have a damn good reason to do it and blase coding needs to go out the window. I ain't even going to talk about cache-coherency!

- Melv.
#12
01/20/2005 (8:26 am)
I'd say that if you knew the concepts of multi-threading you could become an expert in C++ multithreading in a weekend. By in the same token, you could become an expert in C++ recursion over a weekend if you understood the concepts of recursion, but if you don't understand recursion it could take you weeks to wrap your head around the concept properly. Multi-threading is the same way. If you don't understand it, there are problems you will be running into that you don't even know exist or understand. (race conditions and deadlocks, as Melv said) This is one of the few benifits I gleamed from my formal education. Having someone explain these things was invaluable, because prior to college I didn't know anyone in real life who was a programmer. (You wouldn't belive how long it took me to move from BASIC to working in C just because of pointers. I just did not understand the concept at all until it finally clicked.)

Anyway though, back to the topic, it is not our intent that our engines stay single threaded forever.
#13
01/20/2005 (8:31 am)
... and when the TGE becomes more thread-safe, I'll be the first one to test it to death! Okay, maybe the 753rd person but I will definately test it. ;)

That's actually really good news Pat although I guess it's probably way down on the list of priorities. Still good to hear. :)

- Melv.
#14
01/20/2005 (11:25 am)
*cough*TSE terrain uses a background loader thread*coughcough*

Multithreading is becoming more important as consumer systems and consoles have the hardware to support it. Simulations can be difficult to break into threads, but as the hardware becomes friendlier the wins get bigger. We will definitely be moving in that direction at some point.
#15
04/23/2005 (9:15 am)
I see that the class is there, in platform/platformThread.h. So at least the API support is present if one understands the issues.

I also see the Mutex class, but I don't see a Lock class to take advantage of it. Something like the CSingleLock class in MFC that allows one to say:

{
CSingleLock lock(mutex);
// do stuff with mutex locked
// exit from scope releases lock
}

(I'm somewhat compulsive about writing exception-safe code.)
#16
04/23/2005 (5:09 pm)
Ah, that's a good design pattern. Got a link to any good pages on multithread coding techniques like that? It would be good to clean up some of my backgrounnd loader code with such things. :)
#17
04/24/2005 (2:27 am)
The ability to create CSingleLock and CMultiLock and associate them with a sync-object in their constructors, on the stack, is a life-saver when writing multi-threaded code. I've spent the last 8 years writing code that leverages multi-processor support and having OO wrappers saves so much time, even at the expense of a little speed.

OO support of basic objects like sync (events), mutex (criticalsections for speed), semaphore, named-events etc would be nice, especially with support for manual/auto reset and stuff like that.

The only references I've got are books. The MSDN MFC/Win32 references for sync-objects are good examples of OO MT although there's no reference for OO thread-process control.

- Melv.
#18
04/24/2005 (8:43 am)
There used to be a great C++ magazine called "C++ Report" that had lots of valuable information for advanced C++ coders. Things like regular columns on ACE, the Adaptive Communications Environment and various design patterns. I probably picked up a lot of exception-safe idioms there, such as the standard template auto_ptr for pointer management and lots of variations on that theme.

The CSingleLock is an instance of a pattern that attempts to reproduce the Java "synchronized" operator, which is applied to a block to insure that only one thread can be in that block at a time.

The current TGE Thread class is a fairly "raw" wrapper for the basic threading API. The pattern I usually see in recent toolkits is an abstract base class with a pure virtual run() method that takes no arguments. The base class constructor takes only a "start_thread" bool to indicate if it should create the thread running. One derives from this class and and stores any thread data in the derived class object, and the derived class defines a run() method that's invoked by the base class' static thread method (the "real" thread function).

Some more references:

www.codeproject.com/threads/ThreadClass.asp

oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-18.html

sunsite.ee/java/whitepaper/java-whitepaper-9.html
#19
05/16/2005 (2:27 am)
Here's a trick I've used to thread large, single-threaded codebases that aren't particularly thread-safe:

Create a lock of some kind. The assumption is that only the thread that has taken the lock is allowed to touch the unsafe code/memory space.

In the unsafe code, take the lock right away, and _almost_ never let it go. For one brief moment, every once in a while, release the lock and immediately take it again, blocking the thread until the lock is available. You need to make sure that you aren't in the middle of anything important when you release the lock.

Meanwhile, in your new thread, you may not do *anything* that touches the memory space of the unsafe code. When you need access to the unsafe memory and function calls, perform a blocking lock. Get in and do your dirty work as quickly as possible, and release.


Torque should handle this pretty well, except for the memory management issue. There's probably some main loop that runs once per tick. At the end of a tick, release and take the lock. A database thread could hit the database at its leisure, and store up some results. Take the lock, knowing that you won't have to wait more than a tick. You cannot store up too many tasks, though.

Memory management, though.... Maybe you could disable the Torque memory manager for most of the thread's activity, and only use it when making actual Torque objects. Ugh, that sounds like a pain.
#20
05/16/2005 (3:30 am)
Or you could put a lock on memory and Con::printf access, which is what I did when I got TSE to be MT safe-ish.
Page «Previous 1 2