(svn r20510) -Codechange: unify packet queue handling and make insertion O(1) instead of O(n)

This commit is contained in:
rubidium 2010-08-15 23:44:45 +00:00
parent 12b8822277
commit 1c3d42598e
4 changed files with 72 additions and 36 deletions

View File

@ -36,12 +36,6 @@ NetworkClientSocket::NetworkClientSocket(ClientID client_id)
NetworkClientSocket::~NetworkClientSocket() NetworkClientSocket::~NetworkClientSocket()
{ {
while (this->command_queue != NULL) {
CommandPacket *p = this->command_queue->next;
free(this->command_queue);
this->command_queue = p;
}
if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID; if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID;
this->client_id = INVALID_CLIENT_ID; this->client_id = INVALID_CLIENT_ID;
this->status = STATUS_INACTIVE; this->status = STATUS_INACTIVE;

View File

@ -74,6 +74,22 @@ enum TCPPacketType {
/** Packet that wraps a command */ /** Packet that wraps a command */
struct CommandPacket; struct CommandPacket;
/** A queue of CommandPackets. */
class CommandQueue {
CommandPacket *first; ///< The first packet in the queue.
CommandPacket *last; ///< The last packet in the queue; only valid when first != NULL.
public:
/** Initialise the command queue. */
CommandQueue() : first(NULL), last(NULL) {}
/** Clear the command queue. */
~CommandQueue() { this->Free(); }
void Append(CommandPacket *p);
CommandPacket *Pop();
CommandPacket *Peek();
void Free();
};
/** Status of a client */ /** Status of a client */
enum ClientStatus { enum ClientStatus {
STATUS_INACTIVE, ///< The client is not connected nor active STATUS_INACTIVE, ///< The client is not connected nor active
@ -106,7 +122,7 @@ public:
ClientStatus status; ///< Status of this client ClientStatus status; ///< Status of this client
CommandPacket *command_queue; ///< The command-queue awaiting delivery CommandQueue command_queue; ///< The command-queue awaiting delivery
NetworkRecvStatus CloseConnection(bool error = true); NetworkRecvStatus CloseConnection(bool error = true);

View File

@ -52,8 +52,53 @@ static CommandCallback * const _callback_table[] = {
/* 0x19 */ CcStartStopVehicle, /* 0x19 */ CcStartStopVehicle,
}; };
/**
* Append a CommandPacket at the end of the queue.
* @param p The packet to append to the queue.
*/
void CommandQueue::Append(CommandPacket *p)
{
assert(p != NULL);
if (this->first == NULL) {
this->first = p;
} else {
this->last->next = p;
}
this->last = p;
}
/**
* Return the first item in the queue and remove it from the queue.
* @return the first item in the queue.
*/
CommandPacket *CommandQueue::Pop()
{
CommandPacket *ret = this->first;
if (ret != NULL) this->first = this->first->next;
return ret;
}
/**
* Return the first item in the queue, but don't remove it.
* @return the first item in the queue.
*/
CommandPacket *CommandQueue::Peek()
{
return this->first;
}
/** Free everything that is in the queue. */
void CommandQueue::Free()
{
CommandPacket *cp;
while ((cp = this->Pop()) != NULL) {
free(cp);
}
}
/** Local queue of packets */ /** Local queue of packets */
static CommandPacket *_local_command_queue = NULL; static CommandQueue _local_command_queue;
/** /**
* Add a command to the local or client socket command queue, * Add a command to the local or client socket command queue,
@ -65,16 +110,7 @@ void NetworkAddCommandQueue(CommandPacket cp, NetworkClientSocket *cs)
{ {
CommandPacket *new_cp = MallocT<CommandPacket>(1); CommandPacket *new_cp = MallocT<CommandPacket>(1);
*new_cp = cp; *new_cp = cp;
(cs == NULL ? _local_command_queue : cs->command_queue).Append(new_cp);
CommandPacket **begin = (cs == NULL ? &_local_command_queue : &cs->command_queue);
if (*begin == NULL) {
*begin = new_cp;
} else {
CommandPacket *c = *begin;
while (c->next != NULL) c = c->next;
c->next = new_cp;
}
} }
/** /**
@ -141,7 +177,7 @@ void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comma
*/ */
void NetworkSyncCommandQueue(NetworkClientSocket *cs) void NetworkSyncCommandQueue(NetworkClientSocket *cs)
{ {
for (CommandPacket *p = _local_command_queue; p != NULL; p = p->next) { for (CommandPacket *p = _local_command_queue.Peek(); p != NULL; p = p->next) {
CommandPacket c = *p; CommandPacket c = *p;
c.callback = 0; c.callback = 0;
c.next = NULL; c.next = NULL;
@ -156,26 +192,24 @@ void NetworkExecuteLocalCommandQueue()
{ {
assert(IsLocalCompany()); assert(IsLocalCompany());
while (_local_command_queue != NULL) { CommandPacket *cp;
while ((cp = _local_command_queue.Peek()) != NULL) {
/* The queue is always in order, which means /* The queue is always in order, which means
* that the first element will be executed first. */ * that the first element will be executed first. */
if (_frame_counter < _local_command_queue->frame) break; if (_frame_counter < cp->frame) break;
if (_frame_counter > _local_command_queue->frame) { if (_frame_counter > cp->frame) {
/* If we reach here, it means for whatever reason, we've already executed /* If we reach here, it means for whatever reason, we've already executed
* past the command we need to execute. */ * past the command we need to execute. */
error("[net] Trying to execute a packet in the past!"); error("[net] Trying to execute a packet in the past!");
} }
CommandPacket *cp = _local_command_queue;
/* We can execute this command */ /* We can execute this command */
_current_company = cp->company; _current_company = cp->company;
cp->cmd |= CMD_NETWORK_COMMAND; cp->cmd |= CMD_NETWORK_COMMAND;
DoCommandP(cp, cp->my_cmd); DoCommandP(cp, cp->my_cmd);
_local_command_queue = _local_command_queue->next; _local_command_queue.Pop();
free(cp); free(cp);
} }
@ -188,12 +222,7 @@ void NetworkExecuteLocalCommandQueue()
*/ */
void NetworkFreeLocalCommandQueue() void NetworkFreeLocalCommandQueue()
{ {
/* Free all queued commands */ _local_command_queue.Free();
while (_local_command_queue != NULL) {
CommandPacket *p = _local_command_queue;
_local_command_queue = _local_command_queue->next;
free(p);
}
} }
/** /**

View File

@ -1618,11 +1618,8 @@ void NetworkServer_ReadPackets(NetworkClientSocket *cs)
static void NetworkHandleCommandQueue(NetworkClientSocket *cs) static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
{ {
CommandPacket *cp; CommandPacket *cp;
while ((cp = cs->command_queue.Pop()) != NULL) {
while ( (cp = cs->command_queue) != NULL) {
SEND_COMMAND(PACKET_SERVER_COMMAND)(cs, cp); SEND_COMMAND(PACKET_SERVER_COMMAND)(cs, cp);
cs->command_queue = cp->next;
free(cp); free(cp);
} }
} }