Reworked NetworkQueue as a template class

This commit is contained in:
Kayne Ruse
2013-11-22 19:57:24 +11:00
parent 09f97de0e6
commit cb9aef95ec
7 changed files with 131 additions and 163 deletions
+41
View File
@@ -43,3 +43,44 @@ int main(int argc, char** argv) {
cout << "Clean exit" << endl;
return 0;
}
/*/
#include "thread_safe_queue.hpp"
#include "SDL/SDL.h"
#include <iostream>
using namespace std;
struct Object {
int value = 0;
};
int func(void* arg) {
ThreadSafeQueue<Object>& queue = *reinterpret_cast<ThreadSafeQueue<Object>*>(arg);
while(1) {
Object o = queue.PopFront();
if (o.value != 0) {
cout << o.value;
SDL_Delay(500);
cout << endl;
}
}
}
int main(int, char**) {
ThreadSafeQueue<Object> queue;
SDL_Thread* thread1 = SDL_CreateThread(func, reinterpret_cast<void*>(&queue));
SDL_Thread* thread2 = SDL_CreateThread(func, reinterpret_cast<void*>(&queue));
SDL_Thread* thread3 = SDL_CreateThread(func, reinterpret_cast<void*>(&queue));
while(1) {
SDL_Delay(1000);
Object o;
o.value = 3;
queue.PushBack(o);
}
return 0;
}
//*/
-78
View File
@@ -1,78 +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 "network_queue.hpp"
#include <stdexcept>
NetworkQueue::NetworkQueue() {
lock = SDL_CreateSemaphore(1);
if (!lock) {
throw(std::runtime_error("Failed to create NetworkQueue::lock"));
}
}
NetworkQueue::~NetworkQueue() {
SDL_DestroySemaphore(lock);
}
NetworkPacket NetworkQueue::Push(NetworkPacket packet) {
SDL_SemWait(lock);
queue.push_back(packet);
SDL_SemPost(lock);
return packet;
}
NetworkPacket NetworkQueue::Peek() {
NetworkPacket ret;
SDL_SemWait(lock);
if (queue.size() > 0) {
ret = queue[0];
}
SDL_SemPost(lock);
return ret;
}
NetworkPacket NetworkQueue::Pop() {
NetworkPacket ret;
SDL_SemWait(lock);
if (queue.size() > 0) {
ret = queue[0];
queue.pop_front();
}
SDL_SemPost(lock);
return ret;
}
void NetworkQueue::Flush() {
SDL_SemWait(lock);
queue.clear();
SDL_SemPost(lock);
}
int NetworkQueue::Size() {
//can't be sure if std::deque::size() is thread safe
int ret;
SDL_SemWait(lock);
ret = queue.size();
SDL_SemPost(lock);
return ret;
}
-49
View File
@@ -1,49 +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 NETWORKQUEUE_HPP_
#define NETWORKQUEUE_HPP_
#include "network_packet.hpp"
#include "SDL/SDL_thread.h"
#include <deque>
class NetworkQueue {
public:
NetworkQueue();
~NetworkQueue();
NetworkPacket Push(NetworkPacket);
NetworkPacket Peek();
NetworkPacket Pop();
void Flush();
int Size();
SDL_sem* GetLock() const { return lock; }
private:
std::deque<NetworkPacket> queue;
SDL_sem* lock;
};
#endif
+15 -15
View File
@@ -34,7 +34,7 @@ using namespace std;
//Declarations
//-------------------------
int ServerApplication::ClientEntry::indexCounter = 0;
//int ServerApplication::ClientEntry::indexCounter = 0;
//-------------------------
//Define the network thread
@@ -50,7 +50,7 @@ int networkQueueThread(void* ptr) {
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.Push(packet);
app->networkQueue.PushBack(packet);
}
SDL_Delay(10);
}
@@ -127,7 +127,7 @@ void ServerApplication::Loop() {
while(running) {
while(networkQueue.Size() > 0) {
try {
HandlePacket(networkQueue.Pop());
HandlePacket(networkQueue.PopFront());
}
catch(exception& e) {
cerr << "Network Error: " << e.what() << endl;
@@ -152,24 +152,24 @@ void ServerApplication::Quit() {
void ServerApplication::HandlePacket(NetworkPacket packet) {
switch(packet.meta.type) {
case NetworkPacket::Type::PING:
//NOT USED
break;
case NetworkPacket::Type::PONG:
//NOT USED
break;
// case NetworkPacket::Type::PING:
// //NOT USED
// break;
// case NetworkPacket::Type::PONG:
// //NOT USED
// break;
case NetworkPacket::Type::BROADCAST_REQUEST:
cout << "Recieved a request" << endl;
break;
case NetworkPacket::Type::BROADCAST_RESPONSE:
//
break;
// case NetworkPacket::Type::BROADCAST_RESPONSE:
// //
// break;
case NetworkPacket::Type::JOIN_REQUEST:
//
break;
case NetworkPacket::Type::JOIN_RESPONSE:
//
break;
// case NetworkPacket::Type::JOIN_RESPONSE:
// //
// break;
case NetworkPacket::Type::DISCONNECT:
//
break;
+3 -12
View File
@@ -23,7 +23,8 @@
#define SERVERAPPLICATION_HPP_
#include "config_utility.hpp"
#include "network_queue.hpp"
#include "network_packet.hpp"
#include "thread_safe_queue.hpp"
#include "udp_network_utility.hpp"
#include "world_room.hpp"
@@ -31,8 +32,6 @@
#include "SDL/SDL.h"
#include "SDL/SDL_thread.h"
#include <list>
//The main application class
class ServerApplication {
public:
@@ -54,19 +53,11 @@ private:
//networking
UDPNetworkUtility networkUtil;
NetworkQueue networkQueue;
ThreadSafeQueue<NetworkPacket> networkQueue;
SDL_Thread* networkQueueThread = nullptr;
//database
sqlite3* database = nullptr;
//clients
struct ClientEntry {
static int indexCounter;
int index = indexCounter++;
IPaddress add = {0, 0};
};
std::list<ClientEntry> clientEntries;
};
#endif
+68
View File
@@ -0,0 +1,68 @@
#ifndef THREADSAFEQUEUE_HPP_
#define THREADSAFEQUEUE_HPP_
#include "SDL/SDL_thread.h"
#include <deque>
#include <stdexcept>
/* This container is a thread safe reimplementation of std::queue.
*/
template<typename T, class Container = std::deque<T>>
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
+4 -9
View File
@@ -22,13 +22,8 @@
#ifndef WORLDROOM_HPP_
#define WORLDROOM_HPP_
#include "config_utility.hpp"
#include "network_queue.hpp"
#include "udp_network_utility.hpp"
#include "sqlite3/sqlite3.h"
#include "SDL/SDL.h"
#include "SDL/SDL_thread.h"
#include "network_packet.hpp"
#include "thread_safe_queue.hpp"
class WorldRoom {
public:
@@ -39,11 +34,11 @@ public:
void Loop();
void Quit();
NetworkQueue* GetQueue() { return &networkQueue; }
ThreadSafeQueue<NetworkPacket>* GetNetworkQueue() { return &networkQueue; }
private:
void HandlePacket(NetworkPacket);
NetworkQueue networkQueue;
ThreadSafeQueue<NetworkPacket> networkQueue;
};
#endif