Fixed minor errors in Tycho's code
Everything should work now :)
This commit is contained in:
+21
-35
@@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
cEvent::cEvent(void) :
|
||||
m_ShouldWait(true)
|
||||
m_ShouldContinue(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -23,12 +23,11 @@ cEvent::cEvent(void) :
|
||||
|
||||
void cEvent::Wait(void)
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(m_Mutex);
|
||||
while (m_ShouldWait)
|
||||
{
|
||||
m_CondVar.wait(Lock);
|
||||
std::unique_lock<std::mutex> Lock(m_Mutex);
|
||||
m_CondVar.wait(Lock, [this](){ return m_ShouldContinue.load(); });
|
||||
}
|
||||
m_ShouldWait = true;
|
||||
m_ShouldContinue = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,33 +37,13 @@ void cEvent::Wait(void)
|
||||
bool cEvent::Wait(unsigned a_TimeoutMSec)
|
||||
{
|
||||
auto dst = std::chrono::system_clock::now() + std::chrono::milliseconds(a_TimeoutMSec);
|
||||
std::unique_lock<std::mutex> Lock(m_Mutex); // We assume that this lock is acquired without much delay - we are the only user of the mutex
|
||||
while (m_ShouldWait && (std::chrono::system_clock::now() <= dst))
|
||||
bool Result;
|
||||
{
|
||||
switch (m_CondVar.wait_until(Lock, dst))
|
||||
{
|
||||
case std::cv_status::no_timeout:
|
||||
{
|
||||
// The wait was successful, check for spurious wakeup:
|
||||
if (!m_ShouldWait)
|
||||
{
|
||||
m_ShouldWait = true;
|
||||
return true;
|
||||
}
|
||||
// This was a spurious wakeup, wait again:
|
||||
continue;
|
||||
}
|
||||
|
||||
case std::cv_status::timeout:
|
||||
{
|
||||
// The wait timed out, return failure:
|
||||
return false;
|
||||
}
|
||||
} // switch (wait_until())
|
||||
} // while (m_ShouldWait && not timeout)
|
||||
|
||||
// The wait timed out in the while condition:
|
||||
return false;
|
||||
std::unique_lock<std::mutex> Lock(m_Mutex); // We assume that this lock is acquired without much delay - we are the only user of the mutex
|
||||
Result = m_CondVar.wait_until(Lock, dst, [this](){ return m_ShouldContinue.load(); });
|
||||
}
|
||||
m_ShouldContinue = false;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,13 +52,20 @@ bool cEvent::Wait(unsigned a_TimeoutMSec)
|
||||
|
||||
void cEvent::Set(void)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(m_Mutex);
|
||||
m_ShouldWait = false;
|
||||
}
|
||||
m_ShouldContinue = true;
|
||||
m_CondVar.notify_one();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void cEvent::SetAll(void)
|
||||
{
|
||||
m_ShouldContinue = true;
|
||||
m_CondVar.notify_all();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +29,11 @@ public:
|
||||
|
||||
/** Sets the event - releases one thread that has been waiting in Wait().
|
||||
If there was no thread waiting, the next call to Wait() will not block. */
|
||||
void Set (void);
|
||||
void Set(void);
|
||||
|
||||
/** Sets the event - releases all threads that have been waiting in Wait().
|
||||
If there was no thread waiting, the next call to Wait() will not block. */
|
||||
void SetAll(void);
|
||||
|
||||
/** Waits for the event until either it is signalled, or the (relative) timeout is passed.
|
||||
Returns true if the event was signalled, false if the timeout was hit or there was an error. */
|
||||
@@ -37,9 +42,9 @@ public:
|
||||
private:
|
||||
|
||||
/** Used for checking for spurious wakeups. */
|
||||
bool m_ShouldWait;
|
||||
std::atomic<bool> m_ShouldContinue;
|
||||
|
||||
/** Mutex protecting m_ShouldWait from multithreaded access. */
|
||||
/** Mutex protecting m_ShouldContinue from multithreaded access. */
|
||||
std::mutex m_Mutex;
|
||||
|
||||
/** The condition variable used as the Event. */
|
||||
|
||||
@@ -134,9 +134,9 @@ bool cIsThread::Wait(void)
|
||||
m_Thread.join();
|
||||
return true;
|
||||
}
|
||||
catch (std::system_error & a_Exception)
|
||||
catch (const std::system_error & a_Exception)
|
||||
{
|
||||
LOGERROR("cIsThread::Wait error %i: could not join thread %s; %s", a_Exception.code().value(), m_ThreadName.c_str(), a_Exception.code().message().c_str());
|
||||
LOGERROR("%s error %i: could not join thread %s; %s", __FUNCTION__, a_Exception.code().value(), m_ThreadName.c_str(), a_Exception.code().message().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,6 @@ protected:
|
||||
/** The overriden Execute() method should check this value periodically and terminate if this is true. */
|
||||
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:
|
||||
cIsThread(const AString & a_ThreadName);
|
||||
virtual ~cIsThread();
|
||||
@@ -51,14 +47,21 @@ public:
|
||||
|
||||
/** Returns true if the thread calling this function is the thread contained within this object. */
|
||||
bool IsCurrentThread(void) const { return std::this_thread::get_id() == m_Thread.get_id(); }
|
||||
|
||||
private:
|
||||
|
||||
protected:
|
||||
/** The name of the thread, used to aid debugging in IDEs which support named threads */
|
||||
AString m_ThreadName;
|
||||
|
||||
/** The thread object which holds the created thread for later manipulation */
|
||||
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. */
|
||||
This prevents the IsCurrentThread() call to fail because of a race-condition where the thread starts before m_Thread has been fully assigned. */
|
||||
cEvent m_evtStart;
|
||||
|
||||
/** Wrapper for Execute() that waits for the initialization event, to prevent race conditions in thread initialization. */
|
||||
void DoExecute(void);
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user