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"
|
2014-01-28 09:00:02 +01:00
|
|
|
#include <mutex>
|
2013-11-28 16:14:42 +01:00
|
|
|
|
2014-01-15 11:03:25 +01:00
|
|
|
namespace Utility
|
2013-11-28 16:14:42 +01:00
|
|
|
{
|
2014-01-15 11:03:25 +01:00
|
|
|
namespace Container
|
2013-11-28 16:14:42 +01:00
|
|
|
{
|
|
|
|
template <typename Type>
|
|
|
|
class ThreadSafeQueue : public IQueue<Type>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ThreadSafeQueue<Type>();
|
2014-01-28 09:00:02 +01:00
|
|
|
ThreadSafeQueue<Type>(const ThreadSafeQueue<Type>& obj);
|
2013-11-28 16:14:42 +01:00
|
|
|
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 );
|
|
|
|
|
2014-02-04 16:27:18 +01:00
|
|
|
virtual void Clear();
|
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
private:
|
|
|
|
class Node
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Type item;
|
|
|
|
Node *next;
|
2014-01-31 22:52:52 +01:00
|
|
|
Node(){ this->next = NULL; };
|
2013-11-28 16:14:42 +01:00
|
|
|
Node(Type item){ this->item = item; this->next = NULL; };
|
|
|
|
~Node() {};
|
|
|
|
};
|
|
|
|
|
|
|
|
Node *front;
|
|
|
|
Node *back;
|
|
|
|
int nrOfNodes;
|
2013-12-09 10:48:43 +01:00
|
|
|
std::mutex stdMutex;
|
2013-11-28 16:14:42 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------
|
|
|
|
//implemented template functions
|
|
|
|
//----------------------------------------------
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
ThreadSafeQueue<Type>::ThreadSafeQueue()
|
|
|
|
{
|
|
|
|
this->front = NULL;
|
|
|
|
this->back = NULL;
|
|
|
|
this->nrOfNodes = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-01-28 09:00:02 +01:00
|
|
|
template < typename Type >
|
|
|
|
ThreadSafeQueue<Type>::ThreadSafeQueue(const ThreadSafeQueue<Type>& obj)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
template < typename Type >
|
|
|
|
ThreadSafeQueue<Type>::~ThreadSafeQueue()
|
|
|
|
{
|
2014-01-07 10:26:09 +01:00
|
|
|
if(!nrOfNodes) return;
|
|
|
|
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.lock();
|
2013-11-28 16:14:42 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
void ThreadSafeQueue<Type>::Push(Type item)
|
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.lock();
|
2013-11-28 16:14:42 +01:00
|
|
|
Node *e = new Node(item);
|
|
|
|
|
|
|
|
if(this->front != NULL)
|
|
|
|
{
|
|
|
|
this->back->next = e;
|
|
|
|
this->back = e;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->front = e;
|
|
|
|
this->back = e;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->nrOfNodes++;
|
|
|
|
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
Type ThreadSafeQueue<Type>::Pop()
|
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.lock();
|
2013-11-28 16:14:42 +01:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
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()
|
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.lock();
|
2013-12-08 23:56:17 +01:00
|
|
|
Type temp = this->front->item;
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
2013-12-04 12:40:49 +01:00
|
|
|
|
2013-12-08 23:56:17 +01:00
|
|
|
return temp;
|
2013-12-04 12:40:49 +01:00
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
Type ThreadSafeQueue<Type>::Back()
|
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.lock();
|
2013-12-08 23:56:17 +01:00
|
|
|
Type temp = this->back->item;
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
2013-11-28 16:14:42 +01:00
|
|
|
|
2013-12-08 23:56:17 +01:00
|
|
|
return temp;
|
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
int ThreadSafeQueue<Type>::Size()
|
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.lock();
|
2013-12-08 23:56:17 +01:00
|
|
|
int size = this->nrOfNodes;
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
2013-12-04 12:40:49 +01:00
|
|
|
|
2013-12-08 23:56:17 +01:00
|
|
|
return size;
|
2013-12-04 12:40:49 +01:00
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
bool ThreadSafeQueue<Type>::IsEmpty()
|
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.lock();
|
2013-12-04 12:40:49 +01:00
|
|
|
if(nrOfNodes == 0 || this->front == NULL)
|
2013-11-28 16:14:42 +01:00
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
2013-11-28 16:14:42 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
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 )
|
|
|
|
{
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.lock();
|
2013-11-28 16:14:42 +01:00
|
|
|
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());
|
|
|
|
}
|
2013-12-09 10:48:43 +01:00
|
|
|
stdMutex.unlock();
|
2013-11-28 16:14:42 +01:00
|
|
|
}
|
|
|
|
|
2014-02-04 16:27:18 +01:00
|
|
|
template < typename Type >
|
|
|
|
void ThreadSafeQueue<Type>::Clear()
|
|
|
|
{
|
|
|
|
while (!IsEmpty())
|
|
|
|
{
|
|
|
|
Pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-28 16:14:42 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|