2013년 3월 28일 목요일

C++ double linked-list Template Queue

< BufferQueue.h - cpp 만들지 말것, 빌드시 링크에러 발생 >
 #ifndef __BUFFER_QUEUE_H__  
 #define __BUFFER_QUEUE_H__  
   
 #include "Mutex.h"  
 #include "CommonType.h"  
   
 template <typename T>  
 class BufferQueue  
 {  
 public:  
      BufferQueue(int maxQueCount);  
      virtual ~BufferQueue();  
   
      int push_back(T *data);  
      T* pop_front();  
   
      int push_front(T *data);  
      T* pop_back();  
   
      void clear();  
      int count() { return m_nCount; }  
      int maxCount() { return m_nMaxQueCount; }  
      bool isFull();  
   
 protected:  
      int                         m_nMaxQueCount;  
      int                         m_nCount;  
      MUTEX                    m_hMutex;  
   
      template <typename DT>  
      class Element  
      {  
           friend class BufferQueue<DT>;  
   
      private:  
           Element(DT *inData) : data(inData), next(NULL), prev(NULL)  
           {}  
   
           DT *data;  
           Element *next, *prev;  
      };  
   
      Element<T> *m_pHead, *m_pTail;  
 };  
   
 // 템플릿은 미리 컴파일이 되어있어야 함  
 template <typename T>  
 BufferQueue<T>::BufferQueue(int maxQueCount)  
 {  
      m_nMaxQueCount = maxQueCount;  
      m_nCount = 0;  
      m_pHead = m_pTail = NULL;  
      MUTEX_INIT(&m_hMutex);  
 }  
   
 template <typename T>  
 BufferQueue<T>::~BufferQueue()  
 {  
      clear();  
      MUTEX_DESTROY(&m_hMutex);  
 }  
   
 template <typename T>  
 void BufferQueue<T>::clear()  
 {  
      MUTEX_LOCK(&m_hMutex);  
   
      Element<T> *tmp;  
      T *data;  
   
      while (m_pHead != NULL)  
      {  
           tmp = m_pHead;  
           m_pHead = tmp->next;  
           data = tmp->data;  
           delete data;  
           delete tmp;  
      }  
   
      m_pHead = m_pTail = NULL;  
      m_nCount = 0;  
   
      MUTEX_UNLOCK(&m_hMutex);  
 }  
   
 template <typename T>  
 int BufferQueue<T>::push_back(T *data)  
 {  
      MUTEX_LOCK(&m_hMutex);  
   
      if (m_nMaxQueCount > 0) {  
           if (m_nCount >= m_nMaxQueCount) {  
                MUTEX_UNLOCK(&m_hMutex);  
                return -1;  
           }  
      }       
   
      Element<T> *elm = new Element<T>(data);  
   
      if (m_pHead == NULL)  
      {  
           m_pHead = elm;  
           m_pTail = elm;  
      }  
      else  
      {  
           elm->prev = m_pTail;  
           m_pTail->next = elm;  
           m_pTail = elm;  
      }  
   
      m_nCount++;  
   
      MUTEX_UNLOCK(&m_hMutex);  
   
      return m_nCount;  
 }  
   
 template <typename T>  
 T* BufferQueue<T>::pop_front()  
 {  
      MUTEX_LOCK(&m_hMutex);  
   
      Element<T> *elm;  
      T *data = NULL;  
   
      if (m_nCount == 0)  
           goto exit;  
   
      if (m_pHead == NULL)  
           goto exit;  
   
      elm = m_pHead;  
      data = m_pHead->data;  
      m_pHead = m_pHead->next;  
      if (m_pHead) m_pHead->prev = NULL;  
      delete elm;  
   
      if (!m_pHead)  
           m_pTail = NULL;  
   
      m_nCount--;  
   
 exit:  
      MUTEX_UNLOCK(&m_hMutex);  
   
      return data;  
 }  
   
 template <typename T>  
 int BufferQueue<T>::push_front(T *data)  
 {  
      MUTEX_LOCK(&m_hMutex);  
   
      if (m_nMaxQueCount > 0) {  
           if (m_nCount >= m_nMaxQueCount) {  
                MUTEX_UNLOCK(&m_hMutex);  
                return -1;  
           }  
      }       
   
      Element<T> *elm = new Element<T>(data);  
   
      if (m_pHead == NULL)  
      {  
           m_pHead = elm;  
           m_pTail = elm;  
      }  
      else  
      {  
           elm->next = m_pHead;  
           m_pHead->prev = elm;  
           m_pHead = elm;  
      }  
   
      m_nCount++;  
   
      MUTEX_UNLOCK(&m_hMutex);  
   
      return m_nCount;  
 }  
   
 template <typename T>  
 T* BufferQueue<T>::pop_back()  
 {  
      MUTEX_LOCK(&m_hMutex);  
   
      Element<T> *elm;  
      T *data = NULL;  
   
      if (m_nCount == 0)  
           goto exit;  
   
      if (m_pTail == NULL)  
           goto exit;  
   
      elm = m_pTail;  
      data = m_pTail->data;  
      m_pTail = m_pTail->prev;  
      if (m_pTail) m_pTail->next = NULL;  
      delete elm;  
   
      if (!m_pTail)  
           m_pHead = NULL;  
   
      m_nCount--;  
   
 exit:  
      MUTEX_UNLOCK(&m_hMutex);  
   
      return data;  
 }  
   
 template <typename T>  
 bool BufferQueue<T>::isFull()  
 {  
      if (m_nMaxQueCount > 0) {  
           return m_nCount>=m_nMaxQueCount;  
      }  
   
      return false;  
 }  
   
 #endif     
< BufferQueue 사용 >

class MediaBuffer
{
public:
enum MediaType mediaType;
char *data;
int size;
int streamIndex;
int keyFrame;
__int64 timestamp;
__int64 pos;
}
...
BufferQueue<MediaBuffer> *m_pVideoQue = new BufferQueue<MediaBuffer>(30);
...
MediaBuffer *pBuffer = new MediaBuffer();
if (m_pVideoQue->push_back(pBuffer) < 0)
    delete pBuffer;
...
MediaBuffer *pBuffer = m_pVideoQue->pop_front();
...

* linked-list 로 할 수도 있지만 향후 확장성을 고려하여 double linked-list 로 구현

댓글 없음:

댓글 쓰기