2017-06-07 6 views
1

J'essaie de comprendre comment utiliser timed_wait. J'ai trouvé seulement quelques exemples (here et here) et j'ai un problème en l'appelant avec un temps absolu. Le code suivant est un exemple simplifié, en réalité tout cela se passe à l'intérieur d'une classe, donc je pensais qu'il serait plus facile de vérifier manuellement mon prédicat au lieu d'avoir à utiliser une liaison et de le passer à timed_wait.Pourquoi boost :: timed_wait bloque-t-il à jamais lorsqu'il est appelé avec un temps absolu?

#include <boost/date_time/posix_time/posix_time.hpp> 
#include <boost/thread.hpp> 
#include <iostream> 

bool done = false; 
boost::mutex mutex; 
boost::thread waitingThread; 
boost::condition_variable cond; 

void wait(boost::posix_time::time_duration dt){ 
    boost::mutex::scoped_lock lock(mutex); 
    boost::system_time x = boost::posix_time::microsec_clock::local_time() + dt; 
    bool timedOut = false; 
    while((done == false) && (x > boost::posix_time::microsec_clock::local_time())) { 
     timedOut = ! cond.timed_wait(lock,x); 
    } 
    if (timedOut){ std::cout << "timeout\n"; } 
    else   { std::cout << "success\n"; } 
} 

void wait2(boost::posix_time::time_duration dt){ 
    boost::mutex::scoped_lock lock(mutex); 
    bool timedOut = ! cond.timed_wait(lock,dt); 
    if (timedOut){ std::cout << "timeout\n"; } 
    else   { std::cout << "success\n"; } 

} 

void test(){ 
    //boost::thread waiter = boost::thread(wait,boost::posix_time::milliseconds(50)); 
    boost::thread waiter = boost::thread(wait2,boost::posix_time::milliseconds(50)); 
    boost::this_thread::sleep(boost::posix_time::milliseconds(2000)); 
} 

La première version bloque pour toujours et je ne comprends pas pourquoi. D'autre part, la deuxième version afaik est sujette à des réveils intempestifs. Comme je l'ai dit, dans le code réel, tout cela est un lieu intérieur d'une classe, afin d'utiliser la surcharge qui prend un prédicat je dois faire quelque chose comme

cond.timed_wait(lock,dt, ?bind?(&Foo::isDone,this)); 

mais je ne suis pas sûr à 100% si un réveil parasite fera timed_wait retour true (si tel est le cas, mon while (x > local_time()) serait superflu.

Répondre

3

Utilisez boost::get_system_time() + dt, qui est basé à UTC, au lieu de local_time() + dt, qui est ajustée fuseau horaire, car wait_lock(...) utilise boost::get_system_time() pour comparer courant temps avec l'heure absolue cible

L'exemple suivant illustre le problème:

int main() { 
    std::cout << "System time: " 
       << boost::get_system_time() << std::endl; 
    std::cout << "Local time: " 
       << boost::posix_time::microsec_clock::local_time() << std::endl; 
} 

Sortie:

System time: 2017-Jun-07 08:47:58.836677 
Local time: 2017-Jun-07 11:47:58.837003 

Ainsi, votre temps basé wait() blocs fonctionnels absolue juste pour quelques heures spécifiées par décalage horaire de votre ordinateur, pas pour toujours .