나는 다음과 같은 코드를 가지고 :구함 : 우아한 해결책은 상태 경주
class TimeOutException
{};
template <typename T>
class MultiThreadedBuffer
{
public:
MultiThreadedBuffer()
{
InitializeCriticalSection(&m_csBuffer);
m_evtDataAvail = CreateEvent(NULL, TRUE, FALSE, NULL);
}
~MultiThreadedBuffer()
{
CloseHandle(m_evtDataAvail);
DeleteCriticalSection(&m_csBuffer);
}
void LockBuffer()
{
EnterCriticalSection(&m_csBuffer);
}
void UnlockBuffer()
{
LeaveCriticalSection(&m_csBuffer);
}
void Add(T val)
{
LockBuffer();
m_buffer.push_back(val);
SetEvent(m_evtDataAvail);
UnlockBuffer();
}
T Get(DWORD timeout)
{
T val;
if (WaitForSingleObject(m_evtDataAvail, timeout) == WAIT_OBJECT_0) {
LockBuffer();
if (!m_buffer.empty()) {
val = m_buffer.front();
m_buffer.pop_front();
}
if (m_buffer.empty()) {
ResetEvent(m_evtDataAvail);
}
UnlockBuffer();
} else {
throw TimeOutException();
}
return val;
}
bool IsDataAvail()
{
return (WaitForSingleObject(m_evtDataAvail, 0) == WAIT_OBJECT_0);
}
std::list<T> m_buffer;
CRITICAL_SECTION m_csBuffer;
HANDLE m_evtDataAvail;
};
단위 테스트는 T의 기본 생성자만큼 하나의 스레드에서 사용/대입 연산자가 '돈 복사 할 때이 코드가 잘 작동하는지 보여줍니다 던지기. 나는 T를 쓰고 있기 때문에 받아 들일 만하다.
내 문제는 Get 메서드입니다. 사용 가능한 데이터가 없으면 (즉, m_evtDataAvail이 설정되지 않은 경우) 몇 개의 스레드가 WaitForSingleObject 호출을 차단할 수 있습니다. 새 데이터를 사용할 수있게되면 모두 Lock() 호출로 넘어갑니다. 하나만 통과하고 데이터를 가져와 계속 진행할 수 있습니다. Unlock()을 한 후 다른 스레드가 계속 이동할 수 있으며 데이터가 없다는 것을 알 수 있습니다. 현재는 기본 객체를 반환합니다.
는 내가 일 할 것은의 WaitForSingleObject 통화로 돌아가려면 그 두 번째 스레드 (및 기타)입니다. 잠금을 해제하고 goto 한 블록을 추가 할 수는 있지만 악의를 느낍니다. 솔루션은 또한 제한 시간을 다시 시작할 것입니다 각 여행 이후 다시 무한 루프의 가능성을 추가하는
. 항목에 시계를 확인하고 각 여행에서 시간 초과를 조정하는 코드를 추가 할 수 있지만이 간단한 Get 메서드는 매우 복잡해지기 시작합니다.
테스트 용이성과 단순성을 유지하면서 이러한 문제를 해결하는 방법에 어떤 아이디어?
오, 누구나 궁금 들어, IsDataAvail 기능은 테스트 용으로 만 존재한다. 프로덕션 코드에는 사용되지 않습니다. 추가 및 가져 오기는 비 테스팅 환경에서 사용되는 유일한 방법입니다.
먼저, 이러한 상황에서 역사적으로 RAII를 사용했습니다. 이 경우 테스트 영역을 늘리지 않기로했습니다. 나는 TDD에 들어가고있다. –
둘째, 기쁘게! if-empty-reset 블록을 if-not-empty-set으로 변경했는데 생각할 수있는 모든 경로가 제대로 처리됩니다. 감사! –
+1, 자동 집계를 사용합니다. 여기에 autoReset을 사용하면 단점이 있습니다. Add 메서드를 사용하여 m_buffer에 여러 항목이 추가 된 경우 스레드가 대기 중이지만 m_buffer에 아직 항목이 표시되지 않은 경우가 있습니다. –