2013-11-28 16:14:42 +01:00
|
|
|
#ifndef THREAD_SAFE_QUEUE_H
|
|
|
|
#define THREAD_SAFE_QUEUE_H
|
|
|
|
|
|
|
|
////////////////////////////////////////////
|
|
|
|
// Thread safe queue implemented
|
2013-11-29 09:18:58 +01:00
|
|
|
// with single linked list and template.
|
|
|
|
// uses mutex to lock the queue
|
|
|
|
// otherwise its a standard queue
|
2013-11-28 16:14:42 +01:00
|
|
|
// 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();
|
|
|
|
|
2013-12-04 12:40:49 +01:00
|
|
|
Type item = this->front->item;
|
|
|
|
Node *destroyer = this->front;
|
|
|
|
this->front = front->next;
|
|
|
|
|
|
|
|
delete destroyer;
|
|
|
|
this->nrOfNodes--;
|
2013-11-28 16:14:42 +01:00
|
|
|
|
2013-12-04 12:40:49 +01:00
|
|
|
if(nrOfNodes == 0)
|
|
|
|
{
|
|
|
|
this->front = NULL;
|
|
|
|
this->back = NULL;
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
mutex.UnlockMutex();
|
2013-12-04 12:40:49 +01:00
|
|
|
return item;
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
Type ThreadSafeQueue<Type>::Front()
|
|
|
|
{
|
|
|
|
mutex.LockMutex();
|
2013-12-04 12:40:49 +01:00
|
|
|
|
|
|
|
return this->front->item;
|
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
mutex.UnlockMutex();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
Type ThreadSafeQueue<Type>::Back()
|
|
|
|
{
|
|
|
|
mutex.LockMutex();
|
2013-12-04 12:40:49 +01:00
|
|
|
|
|
|
|
return this->back->item;
|
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
mutex.UnlockMutex();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
int ThreadSafeQueue<Type>::Size()
|
|
|
|
{
|
|
|
|
mutex.LockMutex();
|
2013-12-04 12:40:49 +01:00
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
return this->nrOfNodes;
|
2013-12-04 12:40:49 +01:00
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
mutex.UnlockMutex();
|
|
|
|
}
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
bool ThreadSafeQueue<Type>::IsEmpty()
|
|
|
|
{
|
|
|
|
mutex.LockMutex();
|
2013-12-04 12:40:49 +01:00
|
|
|
if(nrOfNodes == 0 || this->front == NULL)
|
2013-11-28 16:14:42 +01:00
|
|
|
{
|
|
|
|
mutex.UnlockMutex();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mutex.UnlockMutex();
|
|
|
|
}
|
2013-12-04 12:40:49 +01:00
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
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
|
|
|
|
|