I'm currently having a problem regarding joining a finished std::thread. I have a simple consumer class:
//Consumer.h
class Consumer
{
public:
//Ctor, Dtor
void Start();
void Release();
private:
void Run();
std::atomic<bool> m_terminate;
std::thread m_thread;
};
//Consumer.cpp
void Consumer::Start()
{
m_thread = std::thread(&EncodingProcessor::Run, this);
}
void Consumer::Release()
{
m_terminate = true;
if (m_thread.joinable())
m_thread.join(); //Here is the deadlock
}
void Consumer::Run()
{
while (true)
{
if (m_terminate)
break;
//This queue is blocking, it is fed with events from an encoder
PMVR::HardwareEncoder::EventWithId currentEvent = m_hwEncoder.GetEncodeEvent();
//If there is an event, again, wait for it, until the according frame is encoded
WaitForSingleObject(currentEvent.handle, INFINITE);
//Lock the encoded bitstream
PMVR::HardwareEncoder::BitStreamBufferInfo currentData =
m_hwEncoder.LockBitstream(currentEvent.id);
std::vector<unsigned char> tmp((unsigned char*)currentData.bitstreamPointer,
(unsigned char*)currentData.bitstreamPointer + currentData.bitstreamSize);
//And process it.
m_consumer->ProcessEncodingResult(currentData.bitstreamPointer, currentData.bitstreamSize);
m_hwEncoder.UnlockBitstream(currentEvent.id);
}
}
So I can start the thread. The thread does what it should. I can end the thread, so the loop inside Run()
gets broken. However, if I want to join the thread, I encounter a deadlock.
We are not talking about the thread beeing released after main()
finished. I can Release()
it via keypress but non of the times it will work.
Edit:
Start()
is called this way:
m_processorThread = new Consumer(*m_hwEncoder,
std::make_unique<FileSystemWriter>("file.h264"));
m_processorThread->Start();
Release()
is called this way:
if (glfwGetKey(handler->GetWindow(), GLFW_KEY_M) && !m_pressed)
{
m_pressed = true;
sessionAPI.Close();
}
sessionAPI.close()
just calls Release()
. Nothing more.
Edit2:
I'm sorry, you are right. The code I've posted so far is working...
So the problem seems to be inside the Run()
method (updated, see above).
So my misconception was, that because of breaking at the top of the loop, the whole stuff beneath it wouldn't get executed... It looks like GetEncodeEvent()
produces the deadlock. But why? Is there an elegant way of breaking the whole loop at a point where the thread isn't waiting for something? In addition, the provider of events is still alive, so there should be notifications...