2009-03-20 8 views
0

In meiner Anwendung möchte ich durch Ereignisse informiert werden, dass eine andere Anwendung gestartet oder gestoppt wurde. Ich habe eine bestehende API zur laufenden Anwendung , die nicht geändert werden kann, um Mitteilung zu empfangen, die die offensichtliche Lösung sein würde.So synchronisieren Sie Threads beim Abfragen von Statusänderungen mit Boost

Was ich habe, ist ein Funktionsaufruf in der API (IsRunning), also habe ich beschlossen, eine Abfrage Thread, der den Status über die API abfragt und informiert meine App.

Mein Problem ist jetzt, der API-Aufruf im Abfragethread verwendet ein Objekt, das auch im Hauptthread meiner eigenen Anwendung verwendet wird, und ich möchte wissen, wie ich sicher sein kann, dass ich es richtig mache :).

Meine Idee wäre, jeden Aufruf an das API-Objekt (über einen Adapter, siehe den zweiten Codeblock) mit einem Mutex-Sperre zu wickeln, so bin ich sicher, dass die API nicht mehr als einmal von meinen Threads aufgerufen wird.

Ist das der richtige Ansatz?

Ich verwende Boost für Threading/Synchronisierung (siehe Code).

Dies ist der Abrufthread:

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

Dies sind einige API-Aufrufe aus dem Haupt-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; 
} 

Antwort

0

Das klingt wie ein guter Ansatz.

Im Allgemeinen sollten Sperren sehr schnell zu erfassen sein, wenn sie nicht beachtet werden. Ihr Abfrage-Thread sollte selten abfragen, d. H. Höchstens einmal alle paar Sekunden, so dass die Konkurrenz auf dem Schloss sehr klein sein sollte.

Wenn Ihre zwei Threads ständig über das Schloss kämpfen, müssen Sie Ihr Design überdenken.