Refactored the input queue to use the new queue type

- Removed all traces of the previous inputMessageQueue type.
- Removed the pointer "next" in inputMessage.
- Rewrote the the main thread and game logic thread to use a queue for input.
This commit is contained in:
Barry Kane 2022-12-19 23:44:16 +00:00
parent 8ae3eaf2b8
commit 9b3df5928b
5 changed files with 37 additions and 149 deletions

View File

@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <pthread.h> #include <pthread.h>
#include "queue.h"
#include "constants.h" #include "constants.h"
#include "gamelogic.h" #include "gamelogic.h"
#include "playerdata.h" #include "playerdata.h"
@ -28,25 +29,21 @@ void * gameLogicLoop(void * parameters)
{ {
evaluateNextCommand(threadParameters, commandQueue); evaluateNextCommand(threadParameters, commandQueue);
} }
// Check for new messages and pop them off the queue: // Check for new messages and pop them off the queue:
if(threadParameters->inputQueue->currentLength != 0) if(threadParameters->inputQueue->itemCount != 0)
{ {
while(threadParameters->inputQueue->lock == true); while(threadParameters->inputQueue->lock == true);
threadParameters->inputQueue->lock = true; threadParameters->inputQueue->lock = true;
currentInput = peekInputMessage(threadParameters->inputQueue); currentInput = peekQueue(threadParameters->inputQueue)->data.inputMessage;
userInputSanatize(currentInput->content->messageContent, MAX); userInputSanatize(currentInput->content->messageContent, MAX);
// A slash as the first character means the message is a user command: // A slash as the first character means the message is a user command:
if(currentInput->content->messageContent[0] == '/') if(currentInput->content->messageContent[0] == '/')
{ {
queueMessagedCommand(commandQueue, currentInput); queueMessagedCommand(commandQueue, currentInput);
} }
else if(currentInput->sender->currentArea == getFromList(threadParameters->areaList, 0)->area)
{ else if (!(currentInput->sender->currentArea == getFromList(threadParameters->areaList, 0)->area))
currentInput = NULL;
threadParameters->inputQueue->lock = false;
dequeueInputMessage(threadParameters->inputQueue);
}
else
{ {
strncpy(currentInput->content->senderName, currentInput->sender->playerName, 32); strncpy(currentInput->content->senderName, currentInput->sender->playerName, 32);
// Create an array of players in the same area to receive the message: // Create an array of players in the same area to receive the message:
@ -72,7 +69,7 @@ void * gameLogicLoop(void * parameters)
} }
currentInput = NULL; currentInput = NULL;
threadParameters->inputQueue->lock = false; threadParameters->inputQueue->lock = false;
dequeueInputMessage(threadParameters->inputQueue); popQueue(threadParameters->inputQueue);
} }
} }
pthread_exit(NULL); pthread_exit(NULL);

View File

@ -2,11 +2,15 @@
// Barry Kane, 2022. // Barry Kane, 2022.
#ifndef GAMELOGIC_H #ifndef GAMELOGIC_H
#define GAMELOGIC_H #define GAMELOGIC_H
#include "queue.h"
#include "areadata.h" #include "areadata.h"
#include "constants.h" #include "constants.h"
#include "playerdata.h" #include "playerdata.h"
#include "inputoutput.h" #include "inputoutput.h"
// Let the compiler know there will be structs defined elsewhere:
typedef struct queue queue;
// ======================= // =======================
// -=[ Main Game Loop ]=-: // -=[ Main Game Loop ]=-:
// ======================= // =======================
@ -17,7 +21,7 @@ typedef struct gameLogicParameters
int * playerCount; int * playerCount;
list * areaList; list * areaList;
playerInfo * connectedPlayers; playerInfo * connectedPlayers;
inputMessageQueue * inputQueue; queue * inputQueue;
outputMessageQueue * outputQueue; outputMessageQueue * outputQueue;
list * globalSkillList; list * globalSkillList;
} gameLogicParameters; } gameLogicParameters;

View File

@ -212,112 +212,6 @@ int dequeueOutputMessage(outputMessageQueue * queue)
} }
} }
inputMessageQueue * createInputMessageQueue(void)
{
inputMessageQueue * newQueue = malloc(sizeof(inputMessageQueue));
newQueue->front = NULL;
newQueue->back = NULL;
newQueue->currentLength = 0;
newQueue->lock = false;
return newQueue;
}
int dequeueInputMessage(inputMessageQueue * queue)
{
// Wait for the queue to unlock:
while (queue->lock);
// Lock the queue:
queue->lock = true;
// Check the list isn't empty:
if(queue->front == NULL)
{
queue->lock = false;
return -1;
}
// If there is only one item in the queue:
else if(queue->front == queue->back)
{
free(queue->front->content);
free(queue->front);
queue->front = NULL;
queue->back = NULL;
queue->currentLength--;
queue->lock = false;
return 0;
}
// Remove the front item:
else
{
inputMessage * messageToDelete = queue->front;
queue->front = queue->front->next;
free(messageToDelete->content);
free(messageToDelete);
queue->currentLength--;
queue->lock = false;
return 0;
}
}
int queueInputMessage(inputMessageQueue * queue, userMessage messageToQueue, playerInfo * sendingPlayer)
{
// Copy the message into a new input message:
inputMessage * input = malloc(sizeof(inputMessage));
// Allocate the internal userMessage to store the message:
input->content = malloc(sizeof(userMessage));
// Copy the userMessage to the internal userMessage:
strncpy(input->content->senderName, messageToQueue.senderName, 32);
strncpy(input->content->messageContent, messageToQueue.messageContent, MAX);
// We have no targets, NULL sends to all players in an area:
input->sender = sendingPlayer;
// Wait for the queue to unlock:
while (queue->lock);
// Lock the queue:
queue->lock = true;
// Check that we're not overflowing the queue:
if ((queue->currentLength + 1) > MAXQUEUELENGTH)
{
// Unlock the queue:
queue->lock = false;
return -1;
}
else
{
// If the queue is empty, set the first message as both the front and back of the queue:
if(queue->front == NULL)
{
queue->front = input;
queue->back = input;
queue->currentLength++;
// Unlock the queue:
queue->lock = false;
return 0;
}
else
{
queue->back->next = input;
queue->back = input;
queue->currentLength++;
// Unlock the queue:
queue->lock = false;
return 0;
}
}
}
void userInputSanatize(char * inputString, int length) void userInputSanatize(char * inputString, int length)
{ {
for(int index = 0; index <= length; index++) for(int index = 0; index <= length; index++)
@ -345,12 +239,6 @@ void userNameSanatize(char * inputString, int length)
inputString[length - 1] = '\0'; inputString[length - 1] = '\0';
} }
// Return the front inputMessage from an inputMessageQueue:
inputMessage * peekInputMessage(inputMessageQueue * queue)
{
return queue->front;
}
outputMessage * peekOutputMessage(outputMessageQueue * queue) outputMessage * peekOutputMessage(outputMessageQueue * queue)
{ {
return queue->front; return queue->front;

View File

@ -67,32 +67,10 @@ outputMessage * peekOutputMessage(outputMessageQueue * queue);
typedef struct inputMessage inputMessage; typedef struct inputMessage inputMessage;
typedef struct inputMessage typedef struct inputMessage
{ {
inputMessage * next;
playerInfo * sender; playerInfo * sender;
userMessage * content; userMessage * content;
} inputMessage; } inputMessage;
// A first-in first-out queue for message input from players:
typedef struct inputMessageQueue
{
bool lock;
int currentLength;
inputMessage * back;
inputMessage * front;
} inputMessageQueue;
// Create a inputMessageQueue:
inputMessageQueue * createInputMessageQueue(void);
// Enqueue a userMessage to an inputMessageQueue:
int queueInputMessage(inputMessageQueue * queue, userMessage messageToQueue, playerInfo * sendingPlayer);
// Dequeue the front inputMessage from an inputMessageQueue:
int dequeueInputMessage(inputMessageQueue * queue);
// Return the front inputMessage from an inputMessageQueue:
inputMessage * peekInputMessage(inputMessageQueue * queue);
// ======================= // =======================
// -=[Input Sanitation]=-: // -=[Input Sanitation]=-:
// ======================= // =======================

View File

@ -17,6 +17,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
#include "../queue.h"
#include "../areadata.h" #include "../areadata.h"
#include "../gamelogic.h" #include "../gamelogic.h"
#include "../constants.h" #include "../constants.h"
@ -45,7 +46,7 @@ int main(int argc, char ** argv)
playerInfo connectedPlayers[PLAYERCOUNT]; playerInfo connectedPlayers[PLAYERCOUNT];
char testString[32] = "Hehe."; char testString[32] = "Hehe.";
struct sockaddr_in serverAddress, clientAddress; struct sockaddr_in serverAddress, clientAddress;
inputMessageQueue * inputQueue = createInputMessageQueue(); queue * inputQueue = createQueue();
outputMessageQueue * outputQueue = createOutputMessageQueue(); outputMessageQueue * outputQueue = createOutputMessageQueue();
// Parse command-line options: // Parse command-line options:
@ -215,7 +216,7 @@ int main(int argc, char ** argv)
while(true) while(true)
{ {
// Clear the set of file descriptors angad add the master socket: // Clear the set of file descriptors and add the master socket:
FD_ZERO(&connectedClients); FD_ZERO(&connectedClients);
FD_SET(socketFileDesc, &connectedClients); FD_SET(socketFileDesc, &connectedClients);
clientsAmount = socketFileDesc; clientsAmount = socketFileDesc;
@ -275,7 +276,18 @@ int main(int argc, char ** argv)
strcpy(sendBuffer.messageContent, "Welcome to the server!"); strcpy(sendBuffer.messageContent, "Welcome to the server!");
messageSend(tlssessions[index], &sendBuffer); messageSend(tlssessions[index], &sendBuffer);
strcpy(receiveBuffer.messageContent, "/look"); strcpy(receiveBuffer.messageContent, "/look");
queueInputMessage(inputQueue, receiveBuffer, &connectedPlayers[index]);
// Allocate the memory for a new input message:
inputMessage * newMessage = malloc(sizeof(inputMessage));
newMessage->content = malloc(sizeof(userMessage));
// Copy in the correct data:
memcpy(newMessage->content, &receiveBuffer, sizeof(userMessage));
newMessage->sender = &connectedPlayers[index];
// Push the new message onto the queue:
pushQueue(inputQueue, newMessage, INPUT_MESSAGE);
break; break;
} }
} }
@ -315,7 +327,16 @@ int main(int argc, char ** argv)
// Otherwise, they've sent a message: // Otherwise, they've sent a message:
else else
{ {
queueInputMessage(inputQueue, receiveBuffer, &connectedPlayers[index]); // Allocate the memory for a new input message:
inputMessage * newMessage = malloc(sizeof(inputMessage));
newMessage->content = malloc(sizeof(userMessage));
// Copy in the correct data:
memcpy(newMessage->content, &receiveBuffer, sizeof(userMessage));
newMessage->sender = &connectedPlayers[index];
// Push the new message onto the queue:
pushQueue(inputQueue, newMessage, INPUT_MESSAGE);
} }
} }
} }