2009년 12월 07일
우선순위 작업큐 만들기
Active Object Pattern on ACE 에서 이어지는 포스팅 입니다.
로직스레드에서 시간이 오래 걸리는 작업을 처리해 줄 수 없기 때문에 DB작업 같은 것을 다른 스레드에 요청을 합니다. 작업을 다른 스레드로 넘길때 Queue를 사용하는데, Queue는 FIFO 방식이라 먼저 넣은 작업이 먼저 처리됩니다. 하지만, 어떤 경우에는 작업에 우선순위를 부여하고 싶을때가 있습니다. 로그 INSERT 작업 같은 것은 그리 우선 순위가 높은 작업이 아니지만 계정 정보를 읽어오는 작업은 상당히 높은 우선 순위를 가지죠. 이런 경우에 적용할 수 있는 방법입니다.
간단히 설명하면 기존 일반작업큐를 우선순위큐로 바꾸면됩니다. 우선순위큐에 대해서는 여기를 참조하시고 ACE에서는 ACE_Message_Queue가 우선순위큐 기능을 제공합니다. 다행히 지난번 작성한 예제에서 작업을 저장해주는 ACE_Activation_Queue가 내부적으로는 ACE_Message_Qeueu를 사용하기 때문에 ACE_Message_Queue가 제공해주는 기능을 그냥 잘 사용하면 됩니다. 작업을 넣을때 enqueue_prio를 사용하고, DB 스레드에서 작업을 꺼낼때는 dequeue_prio 메소드를 사용하면 되죠.
먼저 작업을 넣을때 우선 순위를 부여하는 코드를 추가합니다.
DB스레드에서 작업을 꺼낼때는 dequeue_prio 메소드를 사용합니다.
ACE_Activation_Queue가 enqueue_prio는 지원하지만 dequeue_prio는 직접 인터페이스를 지원하지 않습니다. queue메소드로 직접 queue 포인터를 얻어와서 dequeue_prio 하면 됩니다.
작업을 넣을때 우선 순위를 지정해서 넣는 것도 잊지 말아야 하겠죠.
priorty가 낮은 숫자일수록 먼저 처리됩니다.
소스파일을 첨부합니다.
ActiveObjectTest.cpp
1~5번 job을 먼저 넣었지만, 우선순위에 밀려 6~10번 작업이 먼저 수행되는 것을 볼수 있습니다.
로직스레드에서 시간이 오래 걸리는 작업을 처리해 줄 수 없기 때문에 DB작업 같은 것을 다른 스레드에 요청을 합니다. 작업을 다른 스레드로 넘길때 Queue를 사용하는데, Queue는 FIFO 방식이라 먼저 넣은 작업이 먼저 처리됩니다. 하지만, 어떤 경우에는 작업에 우선순위를 부여하고 싶을때가 있습니다. 로그 INSERT 작업 같은 것은 그리 우선 순위가 높은 작업이 아니지만 계정 정보를 읽어오는 작업은 상당히 높은 우선 순위를 가지죠. 이런 경우에 적용할 수 있는 방법입니다.
간단히 설명하면 기존 일반작업큐를 우선순위큐로 바꾸면됩니다. 우선순위큐에 대해서는 여기를 참조하시고 ACE에서는 ACE_Message_Queue가 우선순위큐 기능을 제공합니다. 다행히 지난번 작성한 예제에서 작업을 저장해주는 ACE_Activation_Queue가 내부적으로는 ACE_Message_Qeueu를 사용하기 때문에 ACE_Message_Queue가 제공해주는 기능을 그냥 잘 사용하면 됩니다. 작업을 넣을때 enqueue_prio를 사용하고, DB 스레드에서 작업을 꺼낼때는 dequeue_prio 메소드를 사용하면 되죠.
먼저 작업을 넣을때 우선 순위를 부여하는 코드를 추가합니다.
class SelectAccountJob : public ACE_Method_Request
{
public:
virtual int call (void)
{
ACE_DEBUG((LM_INFO, ACE_TEXT ("(%t) Start SelectAccountJob\n")));
ACE_OS::sleep (1);
result_.set("Success");
ACE_DEBUG ((LM_INFO, ACE_TEXT("(%t) End SelectAccountJob\n")));
return 0;
}
void SetPriorty(unsigned long priority)
{
ACE_Method_Request::priority(priority);
}
};
DB스레드에서 작업을 꺼낼때는 dequeue_prio 메소드를 사용합니다.
class DBWorkerThread : public ACE_Task_Base
{
public:
int svc()
{
const int MAX_TIMEOUT = 5;
while(true)
{
ACE_Time_Value tv ((long)MAX_TIMEOUT);
ACE_Message_Block* mb = NULL;
this->queue_.queue()->dequeue_prio(mb, &tv);
if (NULL == mb)
continue;
ACE_Method_Request *request =
reinterpret_cast<ACE_Method_Request *> (mb->base ());
request->call();
}
return 0;
}
int put (ACE_Method_Request *req)
{
return queue_.enqueue(req);
}
private:
ACE_Activation_Queue queue_;
};
ACE_Activation_Queue가 enqueue_prio는 지원하지만 dequeue_prio는 직접 인터페이스를 지원하지 않습니다. queue메소드로 직접 queue 포인터를 얻어와서 dequeue_prio 하면 됩니다.
작업을 넣을때 우선 순위를 지정해서 넣는 것도 잊지 말아야 하겠죠.
unsigned int priorty = 1
job->SetPriorty(priorty);
workerThread.put(job);
priorty가 낮은 숫자일수록 먼저 처리됩니다.
소스파일을 첨부합니다.
ActiveObjectTest.cpp
1~5번 job을 먼저 넣었지만, 우선순위에 밀려 6~10번 작업이 먼저 수행되는 것을 볼수 있습니다.
# by | 2009/12/07 18:00 | Programming | 트랙백 | 덧글(0)



















