Commit 312e2f03 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Parser: Rework teardown sequence

Relying on ParserService to stop the thread was plain undefined
behavior, as the child class would have been destroyed already, meaning
the parser service thread was running using a dangling instance pointer
parent bc76faf7
......@@ -39,6 +39,18 @@ Parser::Parser( MediaLibrary* ml )
{
}
Parser::~Parser()
{
for ( auto& s : m_services )
{
s->signalStop();
}
for ( auto& s : m_services )
{
s->stop();
}
}
void Parser::addService( ServicePtr service )
{
service->initialize( m_ml, this );
......
......@@ -45,6 +45,7 @@ public:
using ServicePtr = std::unique_ptr<ParserService>;
Parser( MediaLibrary* ml );
virtual ~Parser();
void addService( ServicePtr service );
void parse( std::shared_ptr<Media> media, std::shared_ptr<File> file );
void start();
......
......@@ -32,28 +32,6 @@ ParserService::ParserService()
{
}
ParserService::~ParserService()
{
// Alert first:
for ( auto& t : m_threads )
{
if ( t.joinable() )
{
{
std::lock_guard<std::mutex> lock( m_lock );
m_cond.notify_all();
m_stopParser = true;
}
}
}
// Join afterward:
for ( auto& t : m_threads )
{
if ( t.joinable() )
t.join();
}
}
void ParserService::start()
{
// Ensure we don't start multiple times.
......@@ -75,6 +53,30 @@ void ParserService::resume()
m_cond.notify_all();
}
void ParserService::signalStop()
{
for ( auto& t : m_threads )
{
if ( t.joinable() )
{
{
std::lock_guard<std::mutex> lock( m_lock );
m_cond.notify_all();
m_stopParser = true;
}
}
}
}
void ParserService::stop()
{
for ( auto& t : m_threads )
{
if ( t.joinable() )
t.join();
}
}
void ParserService::parse( std::unique_ptr<parser::Task> t )
{
std::lock_guard<std::mutex> lock( m_lock );
......
......@@ -39,11 +39,23 @@ class ParserService
{
public:
ParserService();
virtual ~ParserService();
virtual ~ParserService() = default;
void start();
void pause();
void resume();
///
/// \brief signalStop Will trigger the threads for termination.
/// This doesn't wait for the threads to be done, but ensure they won't
/// queue another operation.
/// This is usefull to ask all the threads to terminate asynchronously, before
/// waiting for them to actually stop in the stop() method.
///
void signalStop();
///
/// \brief stop Effectively wait the the underlying threads to join.
///
void stop();
void parse( std::unique_ptr<parser::Task> t );
void initialize( MediaLibrary* mediaLibrary, IParserCb* parserCb );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment