You got it right. There's no need to store an end of command since, after you've read the command ID you should know exactly which params should follow,and then you should know how many bytes to read till the next command. You may instead want to use a special command and append it at the end of the stream so that, when reading the buffer, you can easily understand if you reached the end of the command list. This command list is API agnostic so you can use with dx/ogl, since it's up to you to define which command your list will support
I use a buffer, with a counter that "points" to the first free byte ( starts at 0 ends at buffer size -1). Every command is a byte (sort of command ID) followed by additional bytes (ie parameters) if needed. If I run out of space, I simple realloc the buffer giving it some more memory than before. During debug, I break on this reallocations so to have an idea of how much memory a buffer needs and with this data, I prealloc the buffer at startup. To my experience, prealloc a few kb (2 or 3) will be more than sufficient and rarely will run out of space.
@servant: I voted up your answer, because I like the way you put it down, and also because I agree with everything you wrote.
IMO, before using STL, or smart pointers or any "advanced" c++ things, a beginner should understand perfectly what is a (raw) pointer, how it's used, why they exists, what is a memory leak and why/how they are related to the use of pointers.
I think everyone should go trough the process of using pointers and discover that somewhere, sometimes, your program is leaking memory. You should fire up your debugger and go figure.
I think this is the only way to learn. When you understand the power of pointers, then you can choose a (may better) approach, like not using new at all for example.
So my complains against "this new trend" is more about the fear that the the new generation of programmers will grow up without understanding the raw power of c/c++. Why using c++ in first place if you don't have the time/will to learn the hard stuff. There are plenty of other languages that will deal with pointers in a transparent way (c# is a good example).
Anyway, in this specific case, I would have used a placement new, over a pre-allocated memory block of 256 * sizeof(Player), maybe with a little care about memory alignment.
The array of 256 pointer to player is still the best option IMO for a few reason:
1) given the player ID, you have O(1) access to the player data
2) search within the array for null pointers is very cache friendly since a single pointer is only 4 or 8 bytew, so the whole array is 1 or 2 KB of memory
3) from a psychologically point of view, calling new when a new player enter the game, and calling delete when he leave, is something that feels right to me
When a player come, you have to initialize a player class. If you use new Player(), the constructor will take care of initialization; if you use an already existing instance of player, then you have to call some method like player[id].initialize() or player[id].whatever() just to setup the class.
I fell like new Player() is better.
The same goes for a player that log off, calling delete player[id] feels better to me than calling player[id].kill()
It's the same thing, just called with different names.
I agree that a std::vector of pointers is a non sense, that's why my solution involve a plain old array of pointers.
I don't understand this new trend against new and delete. In a simple scenario like this, there's no reason not to use new and delete, it's ABC of programming with c++. If you can't handle a simple array of pointers, you have no hope with c++. It's a good exercise for the OP and understanding why he gets an error when deleting a player will save him a lot of troubles in the future.
@burden: your remove fn is correct, the error probably is in your create function
Assuming you won't have more than 256 player online, you can use a plain old array, like Player *players.
Memset to zero and you'll have all players=NULL.
When a player connect, scan the array and look for the first NULL; when a player leave, delete players[id], and set players[id]=null
Thank you. After years of working with row major, I've some trouble figuring the Real Memory layout of a column major Matrix. It makes sense, a column of 3 floats it's represented as a 4float register inside hlsl. That explains everything.