Threadsafe Queue implemented with IQueue interface

threadsafe by using mutex lock in the Queue
This commit is contained in:
Sam Mario Svensson 2013-11-28 16:14:42 +01:00
parent 0c40ca1be5
commit 23fa090296
6 changed files with 314 additions and 4 deletions

31
Code/Misc/IQueue.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef I_QUEUE_H
#define I_QUEUE_H
/////////////////////////////////
// Created by Sam Svensson 2013//
/////////////////////////////////
namespace Oyster
{
namespace Queue
{
template <typename Type>
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<Type> &queue ) = 0;
};
}
}
#endif

View File

@ -156,8 +156,10 @@
<ClCompile Include="WinTimer.cpp" /> <ClCompile Include="WinTimer.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="IQueue.h" />
<ClInclude Include="Resource\OysterResource.h" /> <ClInclude Include="Resource\OysterResource.h" />
<ClInclude Include="Resource\OResource.h" /> <ClInclude Include="Resource\OResource.h" />
<ClInclude Include="ThreadSafeQueue.h" />
<ClInclude Include="Thread\IThreadObject.h" /> <ClInclude Include="Thread\IThreadObject.h" />
<ClInclude Include="Thread\OysterMutex.h" /> <ClInclude Include="Thread\OysterMutex.h" />
<ClInclude Include="Thread\OysterThread.h" /> <ClInclude Include="Thread\OysterThread.h" />

View File

@ -65,5 +65,11 @@
<ClInclude Include="Thread\OysterThread.h"> <ClInclude Include="Thread\OysterThread.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="IQueue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ThreadSafeQueue.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

216
Code/Misc/ThreadSafeQueue.h Normal file
View File

@ -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 <typename Type>
class ThreadSafeQueue : public IQueue<Type>
{
public:
ThreadSafeQueue<Type>();
virtual ~ThreadSafeQueue<Type>();
virtual void Push( Type item );
virtual Type Pop();
virtual Type Front();
virtual Type Back();
virtual int Size();
virtual bool IsEmpty();
virtual void Swap( IQueue<Type> &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<Type>::ThreadSafeQueue()
{
this->front = NULL;
this->back = NULL;
this->nrOfNodes = 0;
}
template < typename Type >
ThreadSafeQueue<Type>::~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<Type>::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<Type>::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<Type>::Front()
{
mutex.LockMutex();
if(front != NULL)
{
return this->front->item;
}
mutex.UnlockMutex();
return NULL;
}
template < typename Type >
Type ThreadSafeQueue<Type>::Back()
{
mutex.LockMutex();
if(back != NULL)
{
return this->back->item;
}
mutex.UnlockMutex();
return NULL;
}
template < typename Type >
int ThreadSafeQueue<Type>::Size()
{
//? behövs denna låsas?
mutex.LockMutex();
return this->nrOfNodes;
mutex.UnlockMutex();
}
template < typename Type >
bool ThreadSafeQueue<Type>::IsEmpty()
{
mutex.LockMutex();
if(nrOfNodes == 0 && this->front == NULL)
{
mutex.UnlockMutex();
return true;
}
else
{
mutex.UnlockMutex();
}
return false;
}
template < typename Type >
void ThreadSafeQueue<Type>::Swap(IQueue<Type> &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

View File

@ -16,8 +16,8 @@ namespace Oyster
{ {
public: public:
Connection() { this->socket = 0; }; Connection() { this->socket = 0; };
Connection(int socket) { this->socket = socket; }; Connection( int socket ) { this->socket = socket; };
virtual ~Connection(); virtual ~Connection();
virtual int InitiateServer( unsigned short port ); virtual int InitiateServer( unsigned short port );
@ -32,7 +32,7 @@ namespace Oyster
private: private:
int InitiateSocket(); int InitiateSocket();
void SetBlockingMode(bool blocking); void SetBlockingMode( bool blocking );
int socket; int socket;

View File

@ -5,6 +5,7 @@
#include "..\NetworkDependencies\Translator.h" #include "..\NetworkDependencies\Translator.h"
#include "..\NetworkDependencies\Protocols.h" #include "..\NetworkDependencies\Protocols.h"
#include "../NetworkDependencies/OysterByte.h" #include "../NetworkDependencies/OysterByte.h"
#include "../../Misc/ThreadSafeQueue.h"
#include "Client.h" #include "Client.h"
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
@ -37,7 +38,61 @@ int main()
wcout << "errorMessage: " << errorTest << endl; wcout << "errorMessage: " << errorTest << endl;
} }
chat(client);
//test queue
//-----------------------------------------
Oyster::Queue::IQueue<int> *test = new Oyster::Queue::ThreadSafeQueue<int>();
Oyster::Queue::IQueue<int> *test2 = new Oyster::Queue::ThreadSafeQueue<int>();
for(int i = 0; i < 100; i++)
{
//test->Push(i);
//cout << test->Pop() << endl;
}
cout << "heeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeej" <<endl;
for(int i = 99; i > -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" <<endl;
int size = test->Size();
for(int i = 0; i < size; i++)
{
//cout << test->Pop() << endl;
}
cout << "TEST2 99-1" <<endl;
size = test2->Size();
for(int i = 0; i < size; i++)
{
//cout << test2->Pop() << endl;
}
cout << test->Front() << " " << test2->Front() <<endl;
delete test;
delete test2;
//chat(client);
ShutdownWinSock(); ShutdownWinSock();