2009-03-20 2 views
0

Dans mon application, je souhaite être informé par les événements qu'une autre application a été démarrée ou arrêtée. J'ai une API existante à l'application en cours d'exécution qui ne peut pas être modifié pour accueillir la notification qui serait la solution évidente. Ce que j'ai est un appel de fonction dans l'API (isRunning), j'ai donc décidé de faire un thread d'interrogation qui interroge l'état via l'API et informe mon application.Comment synchroniser les threads lors de l'interrogation des changements d'état avec boost

Mon problème est maintenant, l'appel API dans le thread d'interrogation utilise un objet qui est également utilisé dans le thread principal de mon propre application et je voudrais savoir comment être sûr que je le fais bien :). Mon idée serait d'enrouler chaque appel à l'objet API (via un adaptateur par exemple, voir le deuxième bloc de code) avec un verrou mutex, donc je suis sûr que l'API n'est pas appelée par mes threads plus d'une fois.

Est-ce la bonne approche? J'utilise boost pour l'enfilage/la synchronisation (voir le code).

C'est le fil conducteur de vote:

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

Voici quelques appels API du thread principal:

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

Répondre

0

Cela sonne comme une bonne approche.

En général, les verrous doivent être très rapides à acquérir lorsqu'ils ne sont pas recommandés. Votre fil d'interrogation doit être interrogé peu fréquemment, c'est-à-dire, au plus une fois toutes les quelques secondes, donc la contention sur le verrou doit être très faible.

Si vos deux threads luttent constamment sur la serrure, vous devrez repenser votre conception.

Questions connexes