Microsoft DirectX 8.0 (C++)

Managing Player Context Data

While player context values are fairly straightforward to handle, there are a couple of issues that you need to be careful with.

The player context value provides you with a quick way to obtain a valid memory address that will presumably be accessed each time a message arrives. However, you must be careful that different parts of your application do not access the data at the same time. Microsoft® DirectPlay® serializes messages associated with a particular player, which guarantees that you will never be handling two messages from the same player at the same time. As long as you only access the data structure from your callback message handler, you can safely access the structure. However, most applications will need to access player data outside the message handler.

If your application accesses the data outside the callback message handler, you must prevent concurrent access by providing some sort of global mechanism to lock the structure. Even if your application does not require such locking in the early stages of development, you should assume that locking will eventually be required, and build it in from the beginning. If your player context values that are indexes into an array, you should also make sure that you read and update that array safely.

Don't deallocate a player's data structure prematurely. When a player leaves the game, you will normally want to deallocate their data structure and free the associated memory. However, be careful about deallocating the structure as soon as you receive a DPN_MSGID_DESTROY_PLAYER message. If your application accesses that structure outside the callback message handler, that data may still be in use when the message arrives. If you simply deallocate the structure as soon as the message arrives, you may cause other parts of your application to fail.

To avoid prematurely deallocating the structure, you should not only provide an application-level locking mechanism, you should also implement some sort of reference counting. Increment this reference count when you create the structure, and every time you use it. Decrement the reference count every time you have finished with the structure, including in your DPN_MSGID_DESTROY_PLAYER message handler. As long as the reference count is non-zero, some part of your application is accessing the structure. Do not deallocate the structure until the reference count drops to zero.