Architecture
Containment comes in three parts. The first part is the C++ DirectX application. This serves as the main user interface for the player. The second part is the MySQL database that contains the world and status of Containment and the final part is the PHP scripts that allow the user interface application to manipulate the Containment database. All three components make up Containment and all three are a fun programming challenge all of their own - okay, technically you are not programming a database but you get what I mean.
The C++ application had to be multi-threaded. The reasoning behind this was that http requests and responses are not real-time, it can takes seconds to process one transaction. I couldn’t have a 3D display pause while the app went off and updated the database so I put the actual database communication code into another thread. When something is needed from the database or the database needs to be updated a transaction is sent to the comms thread which processes it and gets the result. The comms thread itself blocks while waiting for the results but it means the main thread of the application can proceed. The user still has to wait for the results but at least the simulation continues smoothly while those results are coming in. Each communication is a transaction and each transaction is a C++ class derived from a base Transaction class. They all share a common interface composed of three functions called:
Begin
Update
FInish
Update is the actual function that performs the http communication with the server while Begin and Finish are used to provide house keeping tasks. An example of this is player registration. Currently to join the game the player has to register with the Containment Computer and this is done like:
Register user password
While this transaction is being processed we don’t want the player to be able to type the same line in again so in the Begin function the keyboard console is turned off and in the Finish function it is turned on again. So as you can see those functions can be used to provide a measure of serial flow in the game execution. The alternative would have been to deal with duplicate transactions going through at the same time.
Incoming transactions are placed into an ‘in’ list while processed transactions are placed on an ‘out’ list with critical sections being employed to stop concurrency issues raising their ugly little heads. The critical section is entered, the item removed from the list and the critical section is left and the transaction is then processed. This means that very little time is spent in the critical section which hopefully means very little stalls in the main thread or the communications thread.