1
0

cIsThread: Fixed a race condition on thread start.

This commit is contained in:
Mattes D 2014-12-25 00:34:54 +01:00
parent 1d593134da
commit 081e7ddd02
2 changed files with 30 additions and 7 deletions

View File

@ -68,11 +68,22 @@ cIsThread::~cIsThread()
void cIsThread::DoExecute(void)
{
m_evtStart.Wait();
Execute();
}
bool cIsThread::Start(void) bool cIsThread::Start(void)
{ {
try try
{ {
m_Thread = std::thread(&cIsThread::Execute, this); // Initialize the thread:
m_Thread = std::thread(&cIsThread::DoExecute, this);
#if defined (_MSC_VER) && defined(_DEBUG) #if defined (_MSC_VER) && defined(_DEBUG)
if (!m_ThreadName.empty()) if (!m_ThreadName.empty())
@ -81,9 +92,12 @@ bool cIsThread::Start(void)
} }
#endif #endif
// Notify the thread that initialization is complete and it can run its code safely:
m_evtStart.Set();
return true; return true;
} }
catch (std::system_error & a_Exception) catch (const std::system_error & a_Exception)
{ {
LOGERROR("cIsThread::Start error %i: could not construct thread %s; %s", a_Exception.code().value(), m_ThreadName.c_str(), a_Exception.code().message().c_str()); LOGERROR("cIsThread::Start error %i: could not construct thread %s; %s", a_Exception.code().value(), m_ThreadName.c_str(), a_Exception.code().message().c_str());
return false; return false;

View File

@ -25,23 +25,28 @@ In the descending class' constructor call the Start() method to start the thread
class cIsThread class cIsThread
{ {
protected: protected:
/// This is the main thread entrypoint /** This is the main thread entrypoint.
This function, overloaded by the descendants, is called in the new thread. */
virtual void Execute(void) = 0; virtual void Execute(void) = 0;
/// The overriden Execute() method should check this value periodically and terminate if this is true /** The overriden Execute() method should check this value periodically and terminate if this is true. */
volatile bool m_ShouldTerminate; volatile bool m_ShouldTerminate;
private:
/** Wrapper for Execute() that waits for the initialization event, to prevent race conditions in thread initialization. */
void DoExecute(void);
public: public:
cIsThread(const AString & a_ThreadName); cIsThread(const AString & a_ThreadName);
virtual ~cIsThread(); virtual ~cIsThread();
/// Starts the thread; returns without waiting for the actual start /** Starts the thread; returns without waiting for the actual start. */
bool Start(void); bool Start(void);
/// Signals the thread to terminate and waits until it's finished /** Signals the thread to terminate and waits until it's finished. */
void Stop(void); void Stop(void);
/// Waits for the thread to finish. Doesn't signalize the ShouldTerminate flag /** Waits for the thread to finish. Doesn't signalize the ShouldTerminate flag. */
bool Wait(void); bool Wait(void);
/** Returns true if the thread calling this function is the thread contained within this object. */ /** Returns true if the thread calling this function is the thread contained within this object. */
@ -50,6 +55,10 @@ public:
protected: protected:
AString m_ThreadName; AString m_ThreadName;
std::thread m_Thread; std::thread m_Thread;
/** The event that is used to wait with the thread's execution until the thread object is fully initialized.
This prevents the IsCurrentThread() call to fail because of a race-condition. */
cEvent m_evtStart;
} ; } ;