Threadsafe Queue implemented with IQueue interface
threadsafe by using mutex lock in the Queue
This commit is contained in:
parent
0c40ca1be5
commit
23fa090296
|
@ -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
|
|
@ -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" />
|
||||||
|
|
|
@ -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>
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue