blob: b65a5b4c82047268fc9bc2e79f95f0eba8ed372e [file] [log] [blame]
/*
* File: CvQueue.h
* Author: mony
*
* Created on September 26, 2012, 5:29 PM
*/
#ifndef CVQUEUE_H
#define CVQUEUE_H
#include "CvSemaphore.h"
#include "CvMutex.h"
#include "CvLogger.h"
#include <string>
#include <list>
namespace CvShared
{
////////////////////////////////////////////////////////////////////
// CvQueue<T>
/// @brief This templates defines a waiting queue class for elements of type T.
/// The waiting queue is thread-safe and various threads can push
/// elements into its tail.
/// Threads that desire to read an element from the queue's head will
/// be blocked if the queue is empty and when a new element is pushed,
/// the reader will be unblocked.
////////////////////////////////////////////////////////////////////
template <class T>
class CvQueue
{
public:
CvQueue( const char* apName = "" );
~CvQueue();
static const TimeValue_t TIMEOUT_INFINITE = -1;
static const TimeValue_t TIMEOUT_NO_WAIT = 0;
void Push( const T& element );
void PushFront( const T& element );
bool Pop( T& element, const Millisecs& aTimeout = TIMEOUT_INFINITE );
int Size();
private:
typedef std::list<T> CList;
String m_name; ///< The queue name (recommended to be unique)
CList m_list; ///< Holds the queue elements
CvSemaphore m_semaphore; ///< Represents the queue elements count and provides the blocking mechanism
CvMutex m_mutex; ///< Syncronizes multi-threaded access
};
template <class T>
CvQueue<T>::CvQueue( const char* apName ) :
m_name(apName),
m_semaphore( (String("sema4-") + apName).c_str() ),
m_mutex( (String("mutex-") + apName).c_str() )
{
if ( !m_semaphore.Create(0) )
{
LogMessage( enLogLevel_Error, "ERROR: Failed to create semaphore for queue [%s]", m_name.c_str() );
}
if ( !m_mutex.Create() )
{
LogMessage( enLogLevel_Error, "ERROR: Failed to create mutex for queue [%s]", m_name.c_str() );
}
}
template <class T>
CvQueue<T>::~CvQueue()
{}
template <class T>
void CvQueue<T>::Push(const T& element)
{
CvMutexLock lock(m_mutex);
m_list.push_back(element);
m_semaphore.Post();
}
template <class T>
void CvQueue<T>::PushFront(const T& element)
{
CvMutexLock lock(m_mutex);
m_list.push_front(element);
m_semaphore.Post();
}
template <class T>
bool CvQueue<T>::Pop( T& element, const Millisecs& aTimeout )
{
if ( !m_semaphore.Pend( aTimeout ) )
return false;
CvMutexLock lock(m_mutex);
if ( m_list.empty() )
{
LogMessage( enLogLevel_Warning, "ERROR: Queue [%s] is empty, while it shouldn't be", m_name.c_str() );
return false;
}
element = m_list.front();
m_list.pop_front();
return true;
}
template <class T>
int CvQueue<T>::Size()
{
CvMutexLock lock(m_mutex);
int size = m_list.size();
return size;
}
} // namespace CvShared
#endif /* CVQUEUE_H */