How It WorksNow let's take a look at the heart of the whole system: the function that takes a message ID and returns the appropriate class. Let's say I've just received a big blob of data from DirectPlay's receive function, and now I want to convert that blob of data into the appropriate net_message derivative. I call net_message_maker::constructmessage(), giving it the blob of data, and the size of the blob of data. The first thing constructmessage() does is cast the raw data to a generic message. This is the sort of "blind casting" that should make any good C++ programmer freeze in terror, but it's a necessary evil. The DirectX docs even tell us to do it this way. Once we've cast the blob, we know the type of the message: lpMsg->dwType. We look in our m_registry variable, and pull out the correct pair. Then we get the second member of that pair, which is really the this pointer that the constructor registered at program start. (If we can't find the type, m_registry.find() is going to return NULL (or, in debug, 0xcdcdcdcd), which will generate an exception on the next line, and will land us in the exception handler for the function. Not the cleanest way to do things, but it gets the job done). Assuming nothing goes wrong, the local variable "maker" now points to the appropriate factory we should use to construct the message. We then call the makemessage() function of that factory (we can do so, because we have access to the private methods of other instances of ourselves). makemessage() is a pure virtual function, so we'll end up inside of the appropriate maker. makemessage() news up the appropriate net_message derivative, and then tells that instance to deserialize itself from the provided byte blob. Now we have a perfect net_message, all ready to go. From here, you can do whatever you want. Maybe your networking system is like mine, and stores all of the incoming messages in a vector… or maybe you've got some thread action happening, and have a secondary thread processing the messages. That really doesn't matter – what matters is that with one simple function call, constructmessage(), you've transformed a byte blob into a C++ class.
|
|||||||||||