2011년 8월 4일 목요일

미리할당된 버퍼큐(Buffer Queue) 사용하기

링크드리스트로 구성된 메모리가 미리 할당된 버퍼큐
push() 하면 memcpy 가 일어나지만 getBuffer() 함수를 사용하면 push할 버퍼의 포인터를 가져와 엑세스하므로 퍼포먼스를 향상시킬수 있다.

< BufferQueue.h >


#ifndef __BUFFER_QUEUE_H__
#define __BUFFER_QUEUE_H__

#include <windows.h>

#define BUF_SIZE (1024*1024*8)
#define BUF_ELEM_SIZE (30)

typedef struct BufferElement_t {
int len;
char buffer[BUF_SIZE];
BufferElement_t *next;
} BufferElement;

class BufferQueue
{
public:
BufferQueue();
~BufferQueue();

int count;

int push(char *buffer, int len);
BufferElement* pop();
void clear();
BufferElement* getBuffer();
void releaseBuffer();

protected:
BufferElement *head, *tail;
HANDLE hBufferLock;
};

#endif


< BufferQueue.cpp >
#include "BufferQueue.h"

BufferQueue::BufferQueue()
{
count = 0;

hBufferLock = CreateMutex(NULL, FALSE, NULL);

BufferElement *prev = new BufferElement;
prev->len = 0;
head = tail = prev;

for (int i=0; i < BUF_ELEM_SIZE; i++)
{
BufferElement *elem = new BufferElement;
elem->len = 0;
prev->next = elem;
prev = elem;
}

prev->next = head;
}

BufferQueue::~BufferQueue()
{
WaitForSingleObject(hBufferLock, INFINITE);

BufferElement *tmp;
BufferElement *elem = head;

for (int i=0; i < BUF_ELEM_SIZE; i++) {
tmp = elem;
elem = elem->next;
if (tmp)
delete tmp;
}

if (elem)
delete elem;

count = 0;

ReleaseMutex(hBufferLock);

CloseHandle(hBufferLock);
}

BufferElement* BufferQueue::getBuffer()
{
WaitForSingleObject(hBufferLock, INFINITE);

if (count >= BUF_ELEM_SIZE) {
ReleaseMutex(hBufferLock);
return NULL;
}

BufferElement *elem = tail;
tail = tail->next;
count++;

//ReleaseMutex(hBufferLock);

return elem;
}

void BufferQueue::releaseBuffer()
{
ReleaseMutex(hBufferLock);
}

int BufferQueue::push(char *buffer, int len)
{
WaitForSingleObject(hBufferLock, INFINITE);

if (count >= BUF_ELEM_SIZE) {
ReleaseMutex(hBufferLock);
return -1;
}

if (len >= BUF_SIZE) {
ReleaseMutex(hBufferLock);
return -2;
}
tail->len = len;
memcpy(tail->buffer, buffer, len);
tail = tail->next;

count++;

ReleaseMutex(hBufferLock);

return count;
}

BufferElement* BufferQueue::pop()
{
WaitForSingleObject(hBufferLock, INFINITE);

if (count <= 0) {
ReleaseMutex(hBufferLock);
return NULL;
}

BufferElement *elem = head;
head = head->next;
count--;

ReleaseMutex(hBufferLock);

return elem;
}

void BufferQueue::clear()
{
WaitForSingleObject(hBufferLock, INFINITE);
count = 0;
tail = head;
ReleaseMutex(hBufferLock);
}

댓글 없음:

댓글 쓰기