In my application I want to be informed by events, that another application has been started or stopped. I have an existing API to the running application which cannot be changed to accomodate notification which would be the obvious solution.
What I have is a function call in the API (isRunning), so I decided to make a polling thread which polls the state through the API and informs my app.
My problem is now, the API call in the polling thread uses an object which is also used in my own application's main thread and I'd like to know how to be sure that I make it right :).
My idea would be to wrap each call to the API object (through an adapter e.g., see the second code block) with a mutex lock, so I'm sure the API is not called by my threads more than once.
Is this the right approach?
I'm using boost for threading/syncing (see code).
This is the polling thread:
void EventCreator::start()
{
stop();
m_bShouldRun = true;
m_spThread = BoostThreadPtr(new thread(bind(&EventCreator::run,this)));
}
void EventCreator::stop()
{
{
lock_guard<mutex> lock(m_mutex);
m_bShouldRun = false;
m_condition.notify_one();
}
if (m_spThread)
{
m_spThread->join();
m_spThread.reset();
}
}
void EventCreator::run()
{
bool isRTAppRunning = m_pDevice->isApplicationRunning();
while (m_bShouldRun)
{
boost::unique_lock<mutex> lock(m_mutex);
//
if(!m_condition.timed_wait(lock,boost::system_time(boost::get_system_time() + boost::posix_time::milliseconds(25))))
{
// here because of time out, so no sleep necessary
bool isStillRunning = m_pDevice->isApplicationRunning();
if (isRTAppRunning != isStillRunning)
{
if (isStillRunning)
{
// Using SendMessage to main thread => no problem here
notifyAppStarted();
}
else
{
notifyAppStopped();
}
isRTAppRunning = isStillRunning;
}
// in addition to wait above
m_spThread->yield();
}
}
}
These are some API calls from the main thread:
void Device::getData(Int32 byteCnt)
{
mutex::scoped_lock lock(m_monitor);
m_pApi->fetchBytes(&m_buf,byteCnt);
}
bool Device::isApplicationRunning()
{
mutex::scoped_lock lock(m_monitor);
return m_pApi->getState() == DV_RUNNING;
}