Redesign of my game

Started by
14 comments, last by gameplayprogammer 13 years, 7 months ago
I have now decided that my game should allow the user to browse the game world while the game is updating for one game day to the next.

Inorder to do this i will need threads.

I would like to code this myself not use a library

Are there any open source, multi-threaded projects i could browse through to see how it is done?

Advertisement
Does it take so long time to calculate the state for the next day that the player will be waiting?
IMO, you'll have far better luck looking at -- then implementing some simple threading examples, rather than trying to reverse-engineer what the threading is trying to accomplish in a large current project.

Spawning a thread to calculate a new world state is very easy. The real headache is in allowing other threads to safely read or write that data while the first thread is updating it. If you don't use a library that manages thread safety for you, then you'll need a deep understanding of concurrency issues to do it yourself. Some values can safely be read while other threads are writing them without locking. Most though will require you to use some type of semaphore based control structure, or one of its derivatives, such as a critical section/mutex.
Quote:Original post by gameplayprogammer
I have now decided that my game should allow the user to browse the game world while the game is updating for one game day to the next.

Inorder to do this i will need threads.


No, I bet you won't really. Just continue to interleave update() and render() calls as you normally do for your game loop, and add conditional logic to the sub-tasks of update() that do the appropriate things at end-of-day. There's a lot of such work to do? Then stagger it.
@jonathanjansson: Yeah it does, i will have about 1000 different entities in this game, all who could be doing things like buying/selling resources from each other.

@Echkard: I am thinking of using QT or Boost for the multi-threading. I think QT as i will be using the QT designer, gui and widgets. I am happy to use a library to manage thread safety if you know of any.

@Zahlman: 1000 different entities, still think its possible. I have detailed my problem below.

At the moment using one thread there is this long wait as all the entities do their update. You can not browse as the UI has to wait till the AI is finished to process clicks.

My idea was that while the game is in updating state, the human can browse the world but not be able to complete any tasks. So a user can click on any entity and see its info screen while it is doing its end-of-day update.

Gameplay, let's assume your game is running on a single core cpu for a minute. In that case, whether you have one entity or one million, Zahlman's non-threaded approach will be FASTER overall than using threads. Flipping that statement on its head, if your game will run fast enough on a uniprocessor, then you don't "need" threads.

Regarding thread safety, you can find thread-safe collection classes. The problem here is that the locking granularity is so coarse that, for your intended use (two threads with massive amounts of shared state) you'll probably wind up with so much contention that it'll underperform or barely outperform the single-threaded solution.

To get around this, you really need to not just try to 'plug in' some library, but get a basic understanding of concurrency issues -- why threads sometimes need to lock data when accessing it, the times when they can safely read shared data without locking it. This will also teach you how to structure your data (no pun so that either fine-grain locking is possible, or that coarse-grained locking doesn't kill your concurrency.

So don't try to look at a large threaded project. Start with any small threading example that uses the basic synchronization structures. When you know what a semaphore/mutex/critical section is and how to protect data with them, all the above will be clear to you.
Quote:Original post by gameplayprogammer
At the moment using one thread there is this long wait as all the entities do their update. You can not browse as the UI has to wait till the AI is finished to process clicks.

This is actually a really good argument for spawning a worker thread. However, as indicated by another reply to this post, browsing through the source code for an entire game is really overcomplicating things. As a matter of fact, learning how to make your game multi-threaded can be achieved in 20 minutes by simply reading the relevant API documentation for your operating system (eg. MSDN for Windows).
Quote:Original post by Dragonion
Quote:Original post by gameplayprogammer
At the moment using one thread there is this long wait as all the entities do their update. You can not browse as the UI has to wait till the AI is finished to process clicks.

This is actually a really good argument for spawning a worker thread.
No it isn't. It's a really good argument for not shutting down your message pump. A worker thread that goes off and does its own independent task is one thing. A thread that shares massive amounts of state with the main thread (as this one will) is another thing entirely.

Quote:learning how to make your game multi-threaded can be achieved in 20 minutes by simply reading the relevant API documentation for your operating system (eg. MSDN for Windows).
You can learn to spawn a thread easily. Learning about thread safety, synchronization, and how to avoid deadlock and race issues takes a lot longer.


Quote:Original post by Echkard
No it isn't. It's a really good argument for not shutting down your message pump. A worker thread that goes off and does its own independent task is one thing. A thread that shares massive amounts of state with the main thread (as this one will) is another thing entirely.


Exactly how do you conclude that the two threads will share "massive amounts of state" from "My idea was that while the game is in updating state, the human can browse the world but not be able to complete any tasks. So a user can click on any entity and see its info screen while it is doing its end-of-day update." ? If anything, it sounds to me that the updating process is indeed not dependent of this viewing he is trying to accomplish.

Quote:Original post by Echkard
You can learn to spawn a thread easily. Learning about thread safety, synchronization, and how to avoid deadlock and race issues takes a lot longer.


Ok, 25 minutes then if you want to include the section about synchronizing with a critical object. Thread safety, race issues and deadlocks? Exactly how is this relevant to such a relatively simple task he is talking about?
Quote:Original post by DragonionExactly how do you conclude that the two threads will share "massive amounts of state" from "My idea was that while the game is in updating state, the human can browse the world but not be able to complete any tasks. So a user can click on any entity and see its info screen while it is doing its end-of-day update." ? If anything, it sounds to me that the updating process is indeed not dependent of this viewing he is trying to accomplish.
The OP stated the user would be able to browse the world while the game is updating world state. A classic reader-writer scenario. The mere fact that we don't have two writers doesn't eliminate all contention.

Quote:Ok, 25 minutes then if you want to include the section about synchronizing with a critical object. Thread safety, race issues and deadlocks? Exactly how is this relevant to such a relatively simple task he is talking about?
With all due respect, if you say that, I don't believe you've written a multithreaded program that shared large amounts of state. Not one that didn't crash, at least :)

If you really don't know how a thread can cause synchronization issues and program crashes even when only one thread is writing while the other reads, I can dig up some references for so. As one simple example, imagine reading the position of an object where its x coordinate has been updated, but not its y coordinate, putting it in a position where it can't possibly be. Or a collection deque, where a new entry has been added, but the pointers not yet updated.

You can say "oh, just throw a critical section around it", but a critical section means single-threading. When two threads share massive amounts of states, you can actually wind up with worse performance than a single-threaded solution if you use such coarse-grain locking.

This topic is closed to new replies.

Advertisement