Как синхронизировать потоки при опросе изменений состояния с помощью boost - PullRequest
0 голосов
/ 20 марта 2009

В моем приложении я хочу получать уведомления о событиях, что другое приложение было запущено или остановлено. У меня есть существующий API для работающего приложения , который нельзя изменить для размещения уведомлений, что было бы очевидным решением.

У меня есть вызов функции в API (isRunning), поэтому я решил создать поток опроса, который опрашивает состояние через API и информирует мое приложение.

Моя проблема в том, что вызов API в потоке опроса использует объект, который также используется в основном потоке моего собственного приложения, и я хотел бы знать, как быть уверенным, что я все делаю правильно:).

Моя идея заключалась бы в том, чтобы обернуть каждый вызов объекта API (через адаптер, например, см. Второй блок кода) блокировкой мьютекса, поэтому я уверен, что API не вызывается моими потоками более одного раза.

Это правильный подход?

Я использую boost для многопоточности / синхронизации (см. Код).

Это тема опроса:

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();
        }
    }
}

Вот некоторые вызовы API из основного потока:

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;
}

1 Ответ

0 голосов
/ 20 марта 2009

Звучит как хороший подход.

Как правило, замки должны быть очень быстрыми, чтобы их можно было приобрести без присмотра. Ваш поток опроса должен опрашивать нечасто, то есть не чаще, чем раз в несколько секунд, поэтому конкуренция за блокировку должна быть очень маленькой.

Если ваши две нити постоянно борются за блокировку, вам нужно переосмыслить свой дизайн.

...