2011년 8월 26일 금요일

MySQL Connector/Net 에서 utf-8 적용

접속시 connectionString에 "charset=utf8" 추가

MySqlConnection conn = null;
string connStr = "server=" + ip + ";user=" + id + ";database=" + database + ";port=" + port + ";password=" + passwd + ";charset=utf8;";
conn = new MySqlConnection(connStr);

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);
}

멀티모니터 열거하기 - Multiple Monitor Enumeration

모니터가 여러 개인 경우 directdraw api 를 사용해 모니터별로 열거할수 있다.
getScreen() 함수는 지정한 RECT 에 해당하는 모니터를 찾고 모니터 오프셋 값을 RECT 에 넣어줌

//----------------------------------------------------------------------------------
#define  MAX_MONITOR (4)

struct Monitor {
    HMONITOR hMon;
    GUID guid; 
};

class MonitorManager {
    Monitor monitor[MAX_MONITOR];
    int nScreen;
    ...
    int getScreen(RECT *rect);
};

// Enumerate Monitor
struct EnumInfo
{
    BOOL bMultimonSupported;
    HRESULT hr;
};

BOOL WINAPI DDEnumCallbackEx( GUID* pGuid, LPTSTR pszDesc, LPTSTR pszDriverName,
                              VOID* pContext, HMONITOR hmon )
{
MONITORINFO mi;
if (pGuid != NULL && hmon != NULL) {
mi.cbSize = sizeof(mi);
GetMonitorInfo(hmon, &mi);

MonitorManager *manager = (MonitorManager *)pContext;
manager->monitor[manager->nScreen].guid = *pGuid;
manager->monitor[manager->nScreen].hMon = hmon;
manager->nScreen++;
}
    return TRUE; // Keep enumerating
}

BOOL WINAPI DDEnumCallback( GUID* pGuid, LPTSTR pszDesc, LPTSTR pszDriverName,
                            VOID* pContext )
{
    DDEnumCallbackEx(pGuid, pszDesc, pszDriverName, pContext, NULL);
    return FALSE; // Stop enumerating -- For this sample, we don't want any non-display devices
}

HRESULT EnumerateScreens(MonitorManager *manager)
{
    HRESULT hr;
    HMODULE hModule = NULL;
    LPDIRECTDRAWENUMERATEEX pDDEnumEx = NULL;
    EnumInfo enumInfo;

    ZeroMemory(&enumInfo, sizeof(enumInfo));

    hModule = LoadLibrary( TEXT("ddraw.dll") );
    // If ddraw.dll doesn't exist in the search path,
    // then DirectX probably isn't installed, so fail.
    if (hModule == NULL)
        return E_FAIL;
 
    pDDEnumEx = (LPDIRECTDRAWENUMERATEEX) GetProcAddress(hModule,
#ifdef UNICODE
        "DirectDrawEnumerateExW"
#else
        "DirectDrawEnumerateExA"
#endif
        );

manager->nScreen = 0;

    if (pDDEnumEx == NULL)
    {
        // We must be running on an old version of DirectDraw.
        // Therefore MultiMon isn't supported. Fall back on
        // DirectDrawEnumerate to enumerate standard devices on a
        // single-monitor system.
        enumInfo.bMultimonSupported = FALSE;
        hr = DirectDrawEnumerate(DDEnumCallback, manager);
    }
    else
    {
        enumInfo.bMultimonSupported = TRUE;
        hr = pDDEnumEx(DDEnumCallbackEx, manager, DDENUM_ATTACHEDSECONDARYDEVICES);
    }

    // If something failed inside the enumeration, be sure to return that HRESULT

    FreeLibrary(hModule);
    return hr;
}

int MonitorManager::getScreen(RECT *rect)
{
MONITORINFO mi;
HMONITOR hMon = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST);
for (int i=0; i < nScreen; i++) {
if (hMon == monitor[i].hMon) {
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMon, &mi);
OffsetRect(rect, -mi.rcMonitor.left, -mi.rcMonitor.top);
return i;
}
}

return -1;
}