Question

Lors de l'utilisation timed_wait sur un boost::condition_variable avec une durée, sera le temps de l'état d'attente après la durée même si l'utilisateur (ou pnt) modifie le temps du système?

par exemple.

boost::posix_time::time_duration wait_duration(0, 0, 1, 0);  // 1 sec
// ** System time jumps back 15 minutes here. **
if( !signal.timed_wait(lock, wait_duration) )
{
    // Does this condition happen 1 second later, or about 15 minutes later?
}
Était-ce utile?

La solution

A la date d'écriture (novembre 2013), si les changements de temps mur d'horloge pendant que vous êtes en attente sur une variable de condition de surpuissance, il vous suffit de faire de mauvais résultats.

Si vous ne pas doivent renforcer l'utilisation, vous pouvez utiliser ce qu'on appelle la « horloge monotones. » Comme l'horloge monotones n'est pas affecté par les changements de temps horloge murale, il est vulnérable au problème que vous avez décrit. Vous pouvez attendre en toute sécurité 5 secondes en utilisant l'API pthreads en utilisant quelque chose comme ceci:

pthread_condattr_t attr;
pthread_cond_t cond;
struct timespec ts;

pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
pthread_cond_init(&cond, &attr);
pthread_condattr_destroy(&attr);
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += 5;
pthreead_cond_timedwait(&cond, &mutex, &ts);

Vous pouvez vérifier la mise en œuvre de boost :: condition_variable. Peut-être qu'ils vont résoudre ce problème un jour. La mise en œuvre est ici: http: //svn.boost. org / svn / accentuation / tronc / accentuation / fil / pthread / condition_variable.hpp

Autres conseils

Je crois qu'il est une condition de course, bien qu'un très rare. La mise en œuvre de condition_variable :: timed_wait () avec une durée convertit simplement la valeur à un system_time en utilisant get_system_time () + wait_duration. Si les changements de temps du système entre les get_system_time () temps est appelé, et l'heure de fin d'attente calculée est reconverties à un compteur basé tique pour l'appel du système d'exploitation sous-jacente, votre temps d'attente sera erroné.

Pour tester cette idée, sous Windows, je l'ai écrit un programme simple avec un fil générer des sorties tous les 100ms, comme ceci:

for (;;)
{
    boost::this_thread::sleep( boost::get_system_time() +
        boost::posix_time::milliseconds( 100 ) );
    std::cout << "Ping!" << std::endl;
}

Un autre thread a été pour régler l'heure du système de retour une minute dans le passé tous les 100ms (ce fil utilise le niveau du système d'exploitation « Sleep () » appel qui évite les conversions en temps du système):

for ( ;; )
{
    Sleep( 100 );
    SYSTEMTIME sysTime;
    GetSystemTime( &sysTime );
    FILETIME fileTime;
    SystemTimeToFileTime( &sysTime, /*out*/&fileTime );
    ULARGE_INTEGER fileTime64 = (ULARGE_INTEGER(fileTime.dwHighDateTime) << 32) |
        fileTime.dwLowDateTime;
    fileTime64 -= 10000000 * 60;   // one minute in the past
    fileTime.dwHighDateTime = (fileTime64>>32) & 0xFFFFFFFF;
    fileTime.dwLowDateTime = fileTime64 & 0xFFFFFFFF;
    FileTimeToSystemTime( &fileTime, /*out*/&sysTime );
    SetSystemTime( &sysTime );
}

Le premier fil, bien que supposé sortie « Ping! » toutes les 100 millisecondes, enfermés assez rapidement.

À moins que je me manque quelque chose, il semble Boost ne fournit pas d'API qui permettent d'éviter ce problème des conversions internes au temps du système, laissant des applications vulnérables aux changements en dehors de l'horloge.

J'ai vu des problèmes avec cela, si votre processus utilise également des signaux. Je l'utilise aussi les variables de condition Boost avec un temps de durée.

Nous avons un processus qui utilise une minuterie POSIX pour obtenir une synchronisation précise à 20 Hz. Lorsque cette minuterie est activée et le temps est fixé à une date antérieure / heure les blocs variables d'état. Quand je change le dos de temps à la valeur initiale continue la variable de condition.

Je copié la mise en œuvre de Boost et régler le mode d'horloge CLOCK_MONOTONIC. Maintenant fonctionne la variable de condition correctement même si le temps change.

Il aurait été utile s'il y aurait eu la possibilité de définir le mode d'une variable de condition à monotones, mais ce n'est pas possible à ce moment.

problème a été résolu à développer la branche 1.61:

https://svn.boost.org/trac/boost/ticket/6377

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top