/****************************************************************************
                Data Object Queue Template class Class 
                -----------------------------------------

    begin      : 2014/06/13
    copyright  : (C) 2005 Solbox Inc.
    author     : 개발팀 스토리지 담당.
    email      : storage.sd@solbox.com
    version    : 3.4.0

    CopyRight(C) 2005 Solbox Inc. All Rights reserved.
    Redistribution and use in source and binary forms, with or with out
    modification, are not permitted in outside of Solbox Inc.
*****************************************************************************/

/* 참고사항
* 본 Template Class 는 기존 CQueue 클래스가 가지고 있는 문제점을 대체하기 위해 
* 새로 개발된 class 임.
* 자세한 사항은 이슈 #19042 참고
*/

#ifndef __DATA_QUEUE_HPP__
#define __DATA_QUEUE_HPP__

#include <queue>
#include <pthread.h>

#define QUEUE_DEFAULT_MAX_SIZE   0

template <typename T>
class CDataQueue
{
	private:

		// data 객체를 저장할 queue.
		std::queue<T> m_queue;

		// queue 접근을 제어할 뮤텍스 lock.
		pthread_mutex_t m_mutexQueue;

		// queue 의 최대 크기 제한값 저장 변수.
		unsigned int m_uMaxSize;
		
	public:

		// 생성자
		CDataQueue() {
			m_uMaxSize = QUEUE_DEFAULT_MAX_SIZE;
			pthread_mutex_init( &m_mutexQueue, NULL );
		}

		// 소멸자
		~CDataQueue() {
			pthread_mutex_destroy( &m_mutexQueue );
		}
		////////////////////////////////////

		// queue 크기를 반환
		unsigned int GetSize( void );

		// queue Max 크기를 반환
		unsigned int GetMaxSize( void );

		// queue Max 크기를 설정
		void SetMaxSize( unsigned int uMaxSize );

		// 초기화
		void Init( void );

		// Data Object 저장
		bool Push( T const& object );

		// queue 에 저장된 첫번재 element 반환
		// - queue 크기가 0 인 경우 호출시 std::out_of_range 오류가 발생해야 하지만...
		//   예외 처리를 대부분 하지 않으므로... 빈 객체를 반환처리하도록 함.
		//   따라서...꼭 GetSize() 함수를 호출하여 data 가 존재하는지 확인한 후 본 함수 호출할 것.
		T Front( void );

		// queue 에 저장된 첫번재 element 제거
		void Pop( void );
						
};

///////////////////////////////////////////////

// queue 크기를 반환
template <typename T>
unsigned int CDataQueue<T>::GetSize( void )
{
	return m_queue.size();	
}

// queue Max 크기를 반환
template <typename T>
unsigned int CDataQueue<T>::GetMaxSize( void )
{
	return m_uMaxSize;
}

// queue Max 크기를 설정
template <typename T>
void CDataQueue<T>::SetMaxSize( unsigned int uMaxSize )
{
	m_uMaxSize = uMaxSize;
}

// 초기화
template <typename T>
void CDataQueue<T>::Init( void )
{
	// queue clear 처리를 수행.
	// - queue 의 경우 clear 함수가 지원되지 않으므로 size 가 0 이 될때까지 pop 처리	
	pthread_mutex_lock( &m_mutexQueue );

	while( m_queue.empty() == false )
		m_queue.pop();
	
	pthread_mutex_unlock( &m_mutexQueue );
	return;
}

// Data Object 저장
template <typename T>
bool CDataQueue<T>::Push( T const& object )
{
	// 현재 queue size 가 설정된 최대 size 를 이상인 경우 실패 처리.
	if( m_queue.size() >= m_uMaxSize )
		return false;
	else
	{
		pthread_mutex_lock( &m_mutexQueue );
		m_queue.push( object );
		pthread_mutex_unlock( &m_mutexQueue );
		return true;
	}
}
// queue 에 저장된 첫번재 element 반환
template <typename T>
T CDataQueue<T>::Front( void )
{
	// queue 특성상 pop, front 처리시 queue 가 비어있지 않음을 보장해야 한다.
	// - 만약 queue 가 빈 경우.. std::out_of_range 예외를 발생시켜야 하지만...
	//   호출 함수에서 이런 예외를 처리하지 않으므로... 
	//   빈 깡통 객체를 전달한다.

	T object;
	if( m_queue.empty() == false )
	{
		pthread_mutex_lock( &m_mutexQueue );
		object = m_queue.front();
		pthread_mutex_unlock( &m_mutexQueue );
	}
	return object;
}

// queue 에 저장된 첫번재 element 제거
template <typename T>
void CDataQueue<T>::Pop( void )
{
	// queue 특성상 pop, front 처리시 queue 가 비어있지 않음을 보장해야 한다.
	if( m_queue.empty() == false )
	{
		pthread_mutex_lock( &m_mutexQueue );
		m_queue.pop();
		pthread_mutex_unlock( &m_mutexQueue );
	}
	return;
}

#endif /* __DATA_QUEUE_HPP__ */
