Dev/C++2015/04/13 22:55

어제 작업 중에, std::thread join() 에서 hang 이 걸리는 문제가 있어 관려 내용을 적어본다.


1. std::thread 로 생성된 스레드 종료 확인

2. std::thread join() 시, hang 발생


문제는, VC 에서 구현된 std::thread 에서 main() 함수가 종료 이후 즉 main thread 가 종료된 후 std::thread join() 호출 시 내부적으로 사용된 WaitForSingleObject() 에서 무한대기 상태가 발생된 것이다. (MS 공식 입장) VC2013에서도 발생됨.


이는 단순히 std::thread() 구현 문제이기 보다는 모든 worker thread 는 main thread 가 종료되기 전에 종료처리(CloseHandle()) 가 되는게 이상적임.


다만, boost 나 gcc 에서 구현된 std::thread 에서는 발생되지 않는다고 하는데 윈도우 상에서 boost 의 경우에도 어차피 내부적으로 win32 thread API를 호출하여 제어할텐데 어떻게 hang 이 걸리지 않았는지 해보진 않았지만 궁금하긴 함.


결론, VC에서 std::thread join() 은 반드시 main thread(main(), dllmain()) 이 종료되기 전에 호출되어야 함.

'Dev > C++' 카테고리의 다른 글

VC std::thread 문제점  (0) 2015/04/13
lock-free queue 단순 성능 비교  (0) 2013/12/13
Posted by 유근호

TRACKBACK http://microdev.tistory.com/trackback/175 관련글 쓰기

댓글을 달아 주세요

Dev/Multimedia2015/04/13 22:39

Directshow 에서 필터들 간의 data flow rate 은 기준 Clock 의 시간을 따라 진행된다.

directshow 에서는 IReferenceClock 이라는 인터페이스를 제공하고 있으며,  대부분 오디오 렌더러에서 IReferenceClock 를 구현하고 이를 filter chain 에서 각 filter 들간의 기준 clock 으로 사용되어 진다.


참고로 **CLSID_SystemClock** 로 제공되는 COM 객체에서 IRefenceClock 을 구현하고 있으며 이는 시스템 시간처럼 1배속으로 tick 이 증가된다.


작업 중에 배속 설정이 필요하여 IReferenceClock 을 별도로 상속 구현한 내용이다.



#include "stdafx.h"
#include "RateClock.h"


RateClock::RateClock(const int rate_num = 1, const int rate_den = 1)
	: CUnknown(L"rateclock", nullptr)
	, m_rate_num(rate_num)
	, m_rate_den(rate_den)
{
}


RateClock::~RateClock()
{
}

STDMETHODIMP RateClock::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
	HRESULT hr;

	if (riid == IID_IReferenceClock)
	{
		hr = GetInterface((IReferenceClock *) this, ppv);
	}
	else
	{
		hr = CUnknown::NonDelegatingQueryInterface(riid, ppv);
	}
	return hr;
}

HRESULT STDMETHODCALLTYPE RateClock::GetTime(/* [annotation][out] */ _Out_ REFERENCE_TIME *pTime)
{
	auto cur_time = std::chrono::system_clock::now();

	if (m_base_time.time_since_epoch().count() == 0)
	{
		m_base_time = cur_time;
		*pTime = 0;
	}
	else
	{
		auto duration = (cur_time - m_base_time) * m_rate_num / m_rate_den;
		using time_base = std::chrono::duration>;
		*pTime = std::chrono::duration_cast(duration).count();
	}

	return S_OK;
}

HRESULT STDMETHODCALLTYPE RateClock::AdviseTime(/* [in] */ REFERENCE_TIME baseTime, /* [in] */ REFERENCE_TIME streamTime, /* [in] */ HEVENT hEvent, /* [annotation][out] */ _Out_ DWORD_PTR *pdwAdviseCookie)
{
	REFERENCE_TIME due_time = baseTime + streamTime;

	while (true)
	{
		REFERENCE_TIME time = 0;
		GetTime(&time);

		if (time >= due_time)
		{
			SetEvent((HANDLE)hEvent);
			return S_OK;
		}
		
		Sleep(1);
	}
}

HRESULT STDMETHODCALLTYPE RateClock::AdvisePeriodic(/* [in] */ REFERENCE_TIME startTime, /* [in] */ REFERENCE_TIME periodTime, /* [in] */ HSEMAPHORE hSemaphore, /* [annotation][out] */ _Out_ DWORD_PTR *pdwAdviseCookie)
{
	return S_OK;
}

HRESULT STDMETHODCALLTYPE RateClock::Unadvise(/* [in] */ DWORD_PTR dwAdviseCookie)
{
	dwAdviseCookie = 0;
	return S_OK;
}

'Dev > Multimedia' 카테고리의 다른 글

배속설정 IReferenceClock  (0) 2015/04/13
Cloud 기반 동영상 Transcoding 서비스 업체  (0) 2011/12/21
HD급 인코더 연구개발의 기술 장벽  (0) 2010/11/13
FFmpeg AACplus  (0) 2010/08/03
FFmpeg committer 가 되려면...  (0) 2009/10/22
B-Frames in DirectShow  (0) 2009/09/01
Posted by 유근호

TRACKBACK http://microdev.tistory.com/trackback/174 관련글 쓰기

댓글을 달아 주세요


티스토리 툴바