Frage

Bei der Verwendung von timed_wait auf einem boost::condition_variable mit einer Dauer, wird den Wartezustand Auszeit nach der Dauer, auch wenn der Benutzer (oder ntp) ändert die Systemzeit?

z. B.

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?
}
War es hilfreich?

Lösung

Ab dem Zeitpunkt des Schreibens (November 2013), wenn die Wand-Uhr-Zeit ändert, während Sie warten auf eine Boost-Zustandsgröße, werden Sie einfach schlechte Ergebnisse erhalten.

Wenn Sie nicht zu verwenden Boost haben, können Sie verwenden, was das heißt „monotone Uhr.“ Da die monotone Uhr von wanduhr Zeitänderungen nicht betroffen ist, ist es nicht anfällig für das Problem, das Sie beschrieben. Sie können sicher 5 Sekunden warten, bis die pThreads API mit so etwas wie dies mit:

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

können Sie überprüfen die Umsetzung der boost :: condition_variable. Vielleicht beheben sie eines Tages diese. Die Implementierung ist hier: http: //svn.boost. org / svn / boost / trunk / boost / thread / pthread / condition_variable.hpp

Andere Tipps

Ich glaube, es ist eine Race-Bedingung, wenn auch eine sehr selten. Die Umsetzung von condition_variable :: timed_wait () mit einer Dauer einfach konvertiert den Wert in ein system_time mit get_system_time () + wait_duration. Wenn die Systemzeit Änderungen zwischen der Zeit get_system_time () aufgerufen werden, und die berechnete Warte Endzeit auf einen tick-basierten Zähler für den zugrunde liegende Betriebssystem Aufruf rückverwandelt, Ihre Wartezeit falsch.

diese Idee zu testen, auf Windows, schrieb ich ein einfaches Programm mit einem Thread eine Ausgabe alle 100 ms zu erzeugen, wie folgt aus:

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

Ein anderer Thread wurde Einstellen der Systemzeit wieder eine Minute lang in der Vergangenheit alle 100ms (dieser Thread verwendet die OS-Ebene „Sleep ()“ Aufruf, die Conversions Systemzeit vermeidet):

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

Der erste Thread, obwohl angeblich Ausgang "Ping!" alle 100 Millisekunden, eingesperrt ziemlich schnell.

Es sei denn, ich etwas fehlte, so scheint es keinen Boost-APIs bereitstellt, die dieses Problem der internen Konvertierungen Systemzeit zu vermeiden, Anwendungen anfällig für außerhalb Änderungen an die Uhr zu verlassen.

Ich habe einige Probleme mit diesem sehen, wenn Ihr Prozess auch Signale verwendet. Ich benutze auch die Boost-Zustandsgrößen mit einer Dauer der Zeit.

Wir haben einen Prozess, der ein POSIX-Timer verwendet genaues Timing bei 20 Hz zu erhalten. Wenn dieser Timer aktiviert und die Zeit wird zu einer früheren Datum / Uhrzeit der Zustandsgröße Blöcke gesetzt. Wenn ich die Zeit wieder auf den ursprünglichen Wert ändern die Zustandsgröße weiter.

kopiert ich die Implementierung von Boost und stellen Sie die Uhr-Modus zu CLOCK_MONOTONIC. Nun ist die Zustandsgröße korrekt funktioniert, auch wenn die Zeit geändert wird.

Es wäre hilfreich gewesen, wenn es eine Möglichkeit gewesen wäre, den Modus einer Zustandsgröße auf monotones zu setzen, aber das ist in diesem Moment nicht möglich.

Frage wurde auf 1,61 festgelegt Zweig entwickeln:

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top