half sync/half async

Post on 04-Jul-2015

982 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Context

동기 IO 와 비동기 IO를 어떻게하면 사이 좋게 지내게 할수 있을까??

Problem

비동기 IO나 동기IO로 인한 아키텍쳐의 복잡도에 영향을 끼쳐서는 안된다.

비동기 IO작업과 동기 IO작업간의 통신으로 인한 성능저하가발생 해서는 안된다.

Solution

비동기 IO Layer와 동기IO Layer를 분리하여, Queueing layer 를 두어 두 Layer가 서로통신할 수 있도록 한다.

Structure

Class : Synchronous Layer

Responsibility: 동기 IO 처리Collaborator : Queueing

Layer

Class : Asynchronous Layer

Responsibility: 비동기 IO 처리

Collaborator : Queueing LayerExternal EventSource

Class : Queueing Layer

Responsibility: 비동기 Layer와 동기 레이어간 데이터 전달역할.Collaborator : 비동기 Layer

동기 Layer

Class : External Event Source

Responsibility: 비동기 Layer 에서 발생하는 IO에 대한 이벤트 처리.Collaborator : 비동기 Layer

Structure (2)

Synchronous Service Layer

Queueing Layer

AsynchronousService Layer

External Event Source

Async Service

Queue

Sync Service 1 Sync Service 2 Sync Service 3

Dynamics

Implementation동기 IO Layer와 비동기 IO Layer 를 나눈다. 동기 IO Layer 구현비동기 IO Layer 구현

External Event Source 구현Queueing Layer 구현

Queue는 Thread Safe하게 구현!! Sync Layer와 Async Layer에 어떻게 알려주고 통신이 되게할건가??

Implementation(2)intACE_Message_Queue_NT::enqueue (ACE_Message_Block *new_item,

ACE_Time_Value *){ACE_TRACE ("ACE_Message_Queue_NT::enqueue");

ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);if (this->state_ != ACE_Message_Queue_Base::DEACTIVATED){size_t const msize = new_item->total_size ();size_t const mlength = new_item->total_length ();// Note - we send ACTIVATED in the 3rd arg to tell the completion// routine it's _NOT_ being woken up because of deactivate().ULONG_PTR state_to_post;state_to_post = ACE_Message_Queue_Base::ACTIVATED;if (::PostQueuedCompletionStatus (this->completion_port_,

static_cast<DWORD> (msize),state_to_post,reinterpret_cast<LPOVERLAPPED> (new_item)))

{// Update the states once I succeed.this->cur_bytes_ += msize;this->cur_length_ += mlength;return ACE_Utils::truncate_cast<int> (++this->cur_count_);

}}

elseerrno = ESHUTDOWN;

// Fail to enqueue the message.return -1;

}

Implementation(2)intACE_Message_Queue_NT::dequeue (ACE_Message_Block *&first_item,

ACE_Time_Value *timeout){ACE_TRACE ("ACE_Message_Queue_NT::dequeue_head");

{ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);

<<생략>>// Get a message from the completion port.int retv = ::GetQueuedCompletionStatus (this->completion_port_,

&msize,&queue_state,reinterpret_cast<LPOVERLAPPED *> (&first_item),(timeout == 0 ? INFINITE : timeout->msec ()));

{ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1);--this->cur_thrs_; // Decrease waiting thread count.if (retv){if (queue_state == ACE_Message_Queue_Base::ACTIVATED){ // Really get a valid MB from the queue.--this->cur_count_;this->cur_bytes_ -= msize;this->cur_length_ -= first_item->total_length ();return ACE_Utils::truncate_cast<int> (this->cur_count_);

}else // Woken up by deactivate () or pulse ().

errno = ESHUTDOWN;}

}return -1;

}

Conclusion구조가 더 간단해 지고 성능에 영향을 주지 않는다.Sync IO 와 Async IO 레이어의 분리로 상호 의존관계가 없어진다.

메모리 Copy나 Thread 동기화 등에 대한 처리를 주의 깊게 해야한다.디버깅이나 테스트하기 복잡하다.

참고 자료ACEhttp://www.cs.wustl.edu/~schmidt/ACE.html

top related