From 23fa0902960208cb30cb22e2398e87ee754f3b56 Mon Sep 17 00:00:00 2001 From: Sam Mario Svensson Date: Thu, 28 Nov 2013 16:14:42 +0100 Subject: [PATCH] Threadsafe Queue implemented with IQueue interface threadsafe by using mutex lock in the Queue --- Code/Misc/IQueue.h | 31 +++ Code/Misc/Misc.vcxproj | 2 + Code/Misc/Misc.vcxproj.filters | 6 + Code/Misc/ThreadSafeQueue.h | 216 ++++++++++++++++++ Code/Network/NetworkDependencies/Connection.h | 6 +- .../OysterNetworkClient/ClientMain.cpp | 57 ++++- 6 files changed, 314 insertions(+), 4 deletions(-) create mode 100644 Code/Misc/IQueue.h create mode 100644 Code/Misc/ThreadSafeQueue.h diff --git a/Code/Misc/IQueue.h b/Code/Misc/IQueue.h new file mode 100644 index 00000000..8ddc28a9 --- /dev/null +++ b/Code/Misc/IQueue.h @@ -0,0 +1,31 @@ +#ifndef I_QUEUE_H +#define I_QUEUE_H + +///////////////////////////////// +// Created by Sam Svensson 2013// +///////////////////////////////// + +namespace Oyster +{ + namespace Queue + { + template + class IQueue + { + public: + virtual ~IQueue() {}; + virtual void Push( Type item ) = 0; + virtual Type Pop() = 0; + + virtual Type Front() = 0; + virtual Type Back() = 0; + + virtual int Size() = 0; + virtual bool IsEmpty() = 0; + + virtual void Swap( IQueue &queue ) = 0; + }; + } +} + +#endif \ No newline at end of file diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj index ca39cada..124024e2 100644 --- a/Code/Misc/Misc.vcxproj +++ b/Code/Misc/Misc.vcxproj @@ -156,8 +156,10 @@ + + diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters index abee7ddd..55ec07ab 100644 --- a/Code/Misc/Misc.vcxproj.filters +++ b/Code/Misc/Misc.vcxproj.filters @@ -65,5 +65,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/Code/Misc/ThreadSafeQueue.h b/Code/Misc/ThreadSafeQueue.h new file mode 100644 index 00000000..019485ce --- /dev/null +++ b/Code/Misc/ThreadSafeQueue.h @@ -0,0 +1,216 @@ +#ifndef THREAD_SAFE_QUEUE_H +#define THREAD_SAFE_QUEUE_H + +//////////////////////////////////////////// +// Thread safe queue implemented +// with single linked list. +// Created by Sam Svensson 2013 +///////////////////////////////////////////// + +#include "IQueue.h" +#include "Thread/OysterMutex.h" + +namespace Oyster +{ + namespace Queue + { + template + class ThreadSafeQueue : public IQueue + { + public: + ThreadSafeQueue(); + virtual ~ThreadSafeQueue(); + + virtual void Push( Type item ); + virtual Type Pop(); + + virtual Type Front(); + virtual Type Back(); + + virtual int Size(); + virtual bool IsEmpty(); + virtual void Swap( IQueue &queue ); + + private: + class Node + { + public: + Type item; + Node *next; + Node(Type item){ this->item = item; this->next = NULL; }; + ~Node() {}; + }; + + Node *front; + Node *back; + int nrOfNodes; + OysterMutex mutex; + }; + + + + + //---------------------------------------------- + //implemented template functions + //---------------------------------------------- + + template < typename Type > + ThreadSafeQueue::ThreadSafeQueue() + { + this->front = NULL; + this->back = NULL; + this->nrOfNodes = 0; + + } + + template < typename Type > + ThreadSafeQueue::~ThreadSafeQueue() + { + this->mutex.LockMutex(); + + if(this->front != NULL) + { + Node *destroyer; + Node *walker = this->front; + + for(int i = 0; i < this->nrOfNodes; i++) + { + destroyer = walker; + walker = walker->next; + + delete destroyer; + } + + this->front = NULL; + this->back = NULL; + } + + this->mutex.UnlockMutex(); + } + + + template < typename Type > + void ThreadSafeQueue::Push(Type item) + { + Node *e = new Node(item); + + mutex.LockMutex(); + if(this->front != NULL) + { + this->back->next = e; + this->back = e; + } + + else + { + this->front = e; + this->back = e; + } + + this->nrOfNodes++; + + mutex.UnlockMutex(); + } + + template < typename Type > + Type ThreadSafeQueue::Pop() + { + mutex.LockMutex(); + if(this->front != NULL) + { + Type item = this->front->item; + Node *destroyer = this->front; + this->front = front->next; + + delete destroyer; + this->nrOfNodes--; + + if(nrOfNodes == 0) + { + this->front = NULL; + this->back = NULL; + } + return item; + } + + mutex.UnlockMutex(); + + return NULL; + } + + template < typename Type > + Type ThreadSafeQueue::Front() + { + mutex.LockMutex(); + if(front != NULL) + { + return this->front->item; + } + mutex.UnlockMutex(); + + return NULL; + } + + template < typename Type > + Type ThreadSafeQueue::Back() + { + mutex.LockMutex(); + if(back != NULL) + { + return this->back->item; + } + mutex.UnlockMutex(); + + return NULL; + } + + template < typename Type > + int ThreadSafeQueue::Size() + { + //? behövs denna låsas? + mutex.LockMutex(); + return this->nrOfNodes; + mutex.UnlockMutex(); + } + + template < typename Type > + bool ThreadSafeQueue::IsEmpty() + { + mutex.LockMutex(); + if(nrOfNodes == 0 && this->front == NULL) + { + mutex.UnlockMutex(); + return true; + } + + else + { + mutex.UnlockMutex(); + } + return false; + } + + template < typename Type > + void ThreadSafeQueue::Swap(IQueue &queue ) + { + mutex.LockMutex(); + int prevNrOfNodes = this->nrOfNodes; + int size = queue.Size(); + + for(int i = 0; i < size; i++) + { + this->Push(queue.Pop()); + } + + for(int i = 0; i < prevNrOfNodes; i++) + { + queue.Push(this->Pop()); + } + mutex.UnlockMutex(); + } + + + } +} +#endif + diff --git a/Code/Network/NetworkDependencies/Connection.h b/Code/Network/NetworkDependencies/Connection.h index b6b17c60..c69bb0f5 100644 --- a/Code/Network/NetworkDependencies/Connection.h +++ b/Code/Network/NetworkDependencies/Connection.h @@ -16,8 +16,8 @@ namespace Oyster { public: - Connection() { this->socket = 0; }; - Connection(int socket) { this->socket = socket; }; + Connection() { this->socket = 0; }; + Connection( int socket ) { this->socket = socket; }; virtual ~Connection(); virtual int InitiateServer( unsigned short port ); @@ -32,7 +32,7 @@ namespace Oyster private: int InitiateSocket(); - void SetBlockingMode(bool blocking); + void SetBlockingMode( bool blocking ); int socket; diff --git a/Code/Network/OysterNetworkClient/ClientMain.cpp b/Code/Network/OysterNetworkClient/ClientMain.cpp index ce66446f..53cb8506 100644 --- a/Code/Network/OysterNetworkClient/ClientMain.cpp +++ b/Code/Network/OysterNetworkClient/ClientMain.cpp @@ -5,6 +5,7 @@ #include "..\NetworkDependencies\Translator.h" #include "..\NetworkDependencies\Protocols.h" #include "../NetworkDependencies/OysterByte.h" +#include "../../Misc/ThreadSafeQueue.h" #include "Client.h" #pragma comment(lib, "ws2_32.lib") @@ -37,7 +38,61 @@ int main() wcout << "errorMessage: " << errorTest << endl; } - chat(client); + + //test queue + //----------------------------------------- + Oyster::Queue::IQueue *test = new Oyster::Queue::ThreadSafeQueue(); + Oyster::Queue::IQueue *test2 = new Oyster::Queue::ThreadSafeQueue(); + + for(int i = 0; i < 100; i++) + { + //test->Push(i); + //cout << test->Pop() << endl; + } + + cout << "heeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeej" < -1; i--) + { + //test->Push(i); + //cout << test->Pop() << endl; + } + + if(test->IsEmpty()) + { + for(int i = 99; i > -1; i--) + { + test->Push(i); + //cout << test->Pop() << endl; + } + } + + for(int i = 0; i < 50; i++) + { + test2->Push(i); + } + + //test2->Swap(*test); + + cout << "TEST 1-50" <Size(); + for(int i = 0; i < size; i++) + { + //cout << test->Pop() << endl; + } + + cout << "TEST2 99-1" <Size(); + for(int i = 0; i < size; i++) + { + //cout << test2->Pop() << endl; + } + + cout << test->Front() << " " << test2->Front() <