From 1e0ed350fcdec126b5fa359869e60de5229f2a02 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 1 Dec 2013 15:21:00 +1100 Subject: [PATCH] Removed Multithreading, simplifying the server Networking and multithreading working at the same time is really fucking hard. It's better to just have the one thread, and not worry about speed at this stage. --- server/server_application.cpp | 73 ++++++++---------------------- server/server_application.hpp | 12 ++--- server/thread_safe_queue.hpp | 68 ---------------------------- server/world_room.cpp | 83 ----------------------------------- server/world_room.hpp | 44 ------------------- 5 files changed, 23 insertions(+), 257 deletions(-) delete mode 100644 server/thread_safe_queue.hpp delete mode 100644 server/world_room.cpp delete mode 100644 server/world_room.hpp diff --git a/server/server_application.cpp b/server/server_application.cpp index f940edc..d9d6d4b 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -36,30 +36,6 @@ using namespace std; int ClientInformation::counter = 0; -//------------------------- -//Define the network thread -//------------------------- - -/* This thread sucks in the packets sent to the server, and pushes them onto the queue. - * This function is declared as a friend of ServerApplication, because I'm lazy -*/ -int networkQueueThread(void* ptr) { - ServerApplication* app = reinterpret_cast(ptr); - NetworkPacket packet; - - while(app->running) { - //suck in the waiting packets - while(app->networkUtil.Receive()) { - memcpy(&packet, app->networkUtil.GetInData(), sizeof(NetworkPacket)); - //this is important: keep track of the source address - packet.meta.srcAddress = app->networkUtil.GetInPacket()->address; - app->networkQueue.PushBack(packet); - } - SDL_Delay(10); - } - return 0; -} - //------------------------- //Define the ServerApplication //------------------------- @@ -75,12 +51,6 @@ ServerApplication::~ServerApplication() { void ServerApplication::Init(int argc, char** argv) { //TODO: proper command line option parsing - //Check prerequisites - if (!sqlite3_threadsafe()) { - throw(runtime_error("Cannot run without thread safety")); - } - cout << "Thread safety confirmed" << endl; - //load config config.Load("rsc\\config.cfg"); @@ -94,7 +64,7 @@ void ServerApplication::Init(int argc, char** argv) { if (SDLNet_Init()) { throw(runtime_error("Failed to init SDL_net")); } - networkUtil.Open(config.Int("server.port"), sizeof(NetworkPacket)); + network.Open(config.Int("server.port"), sizeof(NetworkPacket)); cout << "initialized SDL_net" << endl; //Init SQL @@ -116,26 +86,25 @@ void ServerApplication::Init(int argc, char** argv) { getline(is, script, '\0'); is.close(); sqlite3_exec(database, script.c_str(), nullptr, nullptr, nullptr); - - //setup the threads - networkQueueThread = SDL_CreateThread(&::networkQueueThread, this); - if (!networkQueueThread) { - throw(runtime_error("Failed to create the networkQueueThread")); - } - cout << "initialized networkQueueThread" << endl; } void ServerApplication::Loop() { //debugging + + NetworkPacket packet; + while(running) { - while(networkQueue.Size() > 0) { - try { - HandlePacket(networkQueue.PopFront()); + //suck in the waiting packets & process them + try { + while(network.Receive()) { + memcpy(&packet, network.GetInData(), sizeof(NetworkPacket)); + packet.meta.srcAddress = network.GetInPacket()->address; + HandlePacket(packet); } - catch(exception& e) { - cerr << "Network Error: " << e.what() << endl; - } - }; + } + catch(exception& e) { + cerr << "Network Error: " << e.what() << endl; + } //give the computer a break SDL_Delay(10); @@ -143,12 +112,8 @@ void ServerApplication::Loop() { } void ServerApplication::Quit() { - //catch all signal - running = false; - //members - SDL_WaitThread(networkQueueThread, nullptr); - networkUtil.Close(); + network.Close(); //APIs sqlite3_close_v2(database); @@ -162,7 +127,7 @@ void ServerApplication::HandlePacket(NetworkPacket packet) { //send back the server's name packet.meta.type = NetworkPacket::Type::BROADCAST_RESPONSE; snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str()); - networkUtil.Send(&packet.meta.srcAddress, &packet, sizeof(NetworkPacket)); + network.Send(&packet.meta.srcAddress, &packet, sizeof(NetworkPacket)); break; case NetworkPacket::Type::JOIN_REQUEST: { //TODO: prevent duplicate logins from the same address? @@ -178,14 +143,14 @@ void ServerApplication::HandlePacket(NetworkPacket packet) { //send the client their info packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE; packet.clientInfo.index = newClient.index; - networkUtil.Send(&newClient.address, &packet, sizeof(NetworkPacket)); + network.Send(&newClient.address, &packet, sizeof(NetworkPacket)); cout << "connect, total: " << clientInfo.size() << endl; } break; case NetworkPacket::Type::DISCONNECT: //disconnect the specified client - networkUtil.Send(&clientInfo[packet.clientInfo.index].address, &packet, sizeof(NetworkPacket)); + network.Send(&clientInfo[packet.clientInfo.index].address, &packet, sizeof(NetworkPacket)); clientInfo.erase(packet.clientInfo.index); cout << "disconnect, total: " << clientInfo.size() << endl; @@ -200,7 +165,7 @@ void ServerApplication::HandlePacket(NetworkPacket packet) { //disconnect all clients packet.meta.type = NetworkPacket::Type::DISCONNECT; for (auto& it : clientInfo) { - networkUtil.Send(&it.second.address, &packet, sizeof(NetworkPacket)); + network.Send(&it.second.address, &packet, sizeof(NetworkPacket)); } cout << "shutting down" << endl; diff --git a/server/server_application.hpp b/server/server_application.hpp index e579fe5..a2d1432 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -24,19 +24,18 @@ //networking #include "network_packet.hpp" -#include "thread_safe_queue.hpp" #include "udp_network_utility.hpp" //APIs #include "sqlite3/sqlite3.h" #include "SDL/SDL.h" -#include "SDL/SDL_thread.h" //misc #include "config_utility.hpp" -#include "world_room.hpp" +//STL #include +#include //hold the client info struct ClientInformation { @@ -56,14 +55,12 @@ public: void Loop(); void Quit(); - friend int networkQueueThread(void*); private: void HandlePacket(NetworkPacket); //networking - UDPNetworkUtility networkUtil; - ThreadSafeQueue networkQueue; - SDL_Thread* networkQueueThread = nullptr; + UDPNetworkUtility network; + std::queue networkQueue; //database sqlite3* database = nullptr; @@ -71,7 +68,6 @@ private: //misc bool running = true; ConfigUtility config; - WorldRoom worldRoom; std::map clientInfo; }; diff --git a/server/thread_safe_queue.hpp b/server/thread_safe_queue.hpp deleted file mode 100644 index 128d555..0000000 --- a/server/thread_safe_queue.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef THREADSAFEQUEUE_HPP_ -#define THREADSAFEQUEUE_HPP_ - -#include "SDL/SDL_thread.h" - -#include -#include - -/* This container is a thread safe reimplementation of std::queue. -*/ - -template> -class ThreadSafeQueue { -public: - ThreadSafeQueue() { - lock = SDL_CreateSemaphore(1); - if (!lock) { - throw(std::runtime_error("Failed to create ThreadSafeQueue::lock")); - } - } - - ~ThreadSafeQueue() { - SDL_DestroySemaphore(lock); - } - - T PushBack(T t) { - SDL_SemWait(lock); - container.push_back(t); - SDL_SemPost(lock); - return t; - } - - T PeekFront() { - T t; - SDL_SemWait(lock); - if (container.size() > 0) { - t = container[0]; - } - SDL_SemPost(lock); - return t; - } - - T PopFront() { - T t; - SDL_SemWait(lock); - if (container.size() > 0) { - t = container[0]; - container.pop_front(); - } - SDL_SemPost(lock); - return t; - } - - int Size() { - //can't be sure if std::deque::size() is thread safe - int ret; - SDL_SemWait(lock); - ret = container.size(); - SDL_SemPost(lock); - return ret; - } - -private: - Container container; - SDL_sem* lock; -}; - -#endif diff --git a/server/world_room.cpp b/server/world_room.cpp deleted file mode 100644 index 91e02bc..0000000 --- a/server/world_room.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013 - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. -*/ -#include "world_room.hpp" - -#include -#include - -using namespace std; - -//------------------------- -//Define the WorldRoom's thread -//------------------------- - -int worldRoomThread(void* ptr) { - WorldRoom* room = reinterpret_cast(ptr); - try { - room->Init(); - room->Loop(); - room->Quit(); - } - catch(std::exception& e) { - cerr << "Fatal Room Error: " << e.what() << endl; - return 1; - } - return 0; -} - -//------------------------- -//Define the WorldRoom's methods -//------------------------- - -WorldRoom::WorldRoom() { - // -} - -WorldRoom::~WorldRoom() { - // -} - -void WorldRoom::Init() { - // -} - -void WorldRoom::Loop() { - // -} - -void WorldRoom::Quit() { - // -} - -void WorldRoom::HandlePacket(NetworkPacket packet) { - switch(packet.meta.type) { - -// case NetworkPacket::Type::SYNCHRONIZE: -// // -// break; - - //handle errors - default: - throw(runtime_error("Unknown NetworkPacket::Type encountered")); - break; - } -} diff --git a/server/world_room.hpp b/server/world_room.hpp deleted file mode 100644 index 0a3fc0f..0000000 --- a/server/world_room.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013 - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. -*/ -#ifndef WORLDROOM_HPP_ -#define WORLDROOM_HPP_ - -#include "network_packet.hpp" -#include "thread_safe_queue.hpp" - -class WorldRoom { -public: - WorldRoom(); - ~WorldRoom(); - - void Init(); - void Loop(); - void Quit(); - - ThreadSafeQueue* GetNetworkQueue() { return &networkQueue; } -private: - void HandlePacket(NetworkPacket); - - ThreadSafeQueue networkQueue; -}; - -#endif