[C++] Threads

Started by
16 comments, last by NotAYakk 16 years, 1 month ago
Ah okay, lots of different opinions :P

I was thinking of just the main loop with a second sub-loop for the network.

Since the network loop will run slower, and the main loop should not suffer from that, I thought it would be nice to let them run parallel...I've only heard of threads yet and not of

"higher-level abstractions like fork-join frameworks, task pools, futures, etc."

Thanks for the ideas, I'll dive more into it and do some more investigation :).

[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Advertisement
Quote:Original post by Antheus
Quote:Original post by the_edd

Again, don't be too afraid of locking. Finding "shortcuts" often leads to buggy code unless you *really* know what you're doing.


Be very afraid of locking.


I should have qualified my statement: don't be afraid of the *costs* of locking at this stage, where the alternatives are much harder to get right and risks involved in omitting locks aren't worth it.

I didn't mean to suggest locking correctly is easy, but you must do it anyway.

On top of the additional advice you gave, I would encourage the O.P to create code that can be run in a single thread when a particular switch is flipped in the code. This allows the ability to test algorithm logic in isolation (more or less) from synchronization logic.
There’s also this technique called “polling” — you can ask a socket if it can be written to/read from — thus allowing you to perform network I/O only when there’s data for you to process. In pseudo-code your main loop can then look like this:
while ( running ) {  if ( networkReady() )    handleNetworkStuff();  handleGameStuff();}
Of course, I don’t know anything about your design and your particular problem, so this might as well not be an option for you. But approach like this has almost always worked for me — I can get non-blocking socket operations without the hassle of threading.
Yes, I might try that first...but I thought the networking part could take up some time...thanks for the idea ^^.
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Quote:Original post by Oxyd
There’s also this technique called “polling” — you can ask a socket if it can be written to/read from — thus allowing you to perform network I/O only when there’s data for you to process. In pseudo-code your main loop can then look like this:
while ( running ) {  if ( networkReady() )    handleNetworkStuff();  handleGameStuff();}
Of course, I don’t know anything about your design and your particular problem, so this might as well not be an option for you. But approach like this has almost always worked for me — I can get non-blocking socket operations without the hassle of threading.

But you need to guarantee that your neworkReady() function is atomic. It's not guaranteed to be so, even if all it does is read a boolean. A thread could be writing to that boolean while you're reading from it, meaning you need a lock anyway.
NextWar: The Quest for Earth available now for Windows Phone 7.
All but the poorest semaphore implementations have a method named something like "TryLock()" where it will not block the calling thread but see if the object is currently lockable, and will do so if it is.

As someone else posted, you could check for this in your game loop. I'd add that you could use the same paradigm for network messages, messages from the OS (i.e. WndProc routine), and anything else involving asynchronous messaging. The messages could all be gathered on seperate threads apart from the main thread (or one seperate thread for all messaging); these seperate threads would "WaitLock()" while the main thread would "TryLock()".

That being said, I also want to echo that game engine design generally does not lend itself well to threading, so you should only do it if you have a very good reason.
Quote:Original post by Sc4Freak
But you need to guarantee that your neworkReady() function is atomic. It's not guaranteed to be so, even if all it does is read a boolean. A thread could be writing to that boolean while you're reading from it, meaning you need a lock anyway.


Um, why would I need that? I was talking about an example of a single-threaded implementation — no “other” thread can write to my variables while I’m reading them — there is no other thread.
If you have many readers and few writers, a reader/writer lock might be a good idea.

A RW lock (which are't that easy to write: there are pitfalls) allows any number of reader threads into it at a time. Or one writer thread.

Existing ones usually deal with starvation problems, but if you whip one out yourself you will almost certainly screw up. :)

...

Generally you should avoid actually writing locking code more than a handful of times. Locks are dangerous.

A non-horrible way to avoid writing locking code is to break your code down into jobs: rendering, UI input, world model, etc.

These jobs communicate to each other over message queues, which are carefully written with locks & stuff to deal with multi-threading.

Each job only communicates via messages. There is no shared data that isn't in the messages.

The downside? You have to copy world state a whole bunch.

This topic is closed to new replies.

Advertisement