Domanda

Quando si utilizza timed_wait su un boost::condition_variable con una durata, sarà il tempo di condizione di attesa dopo la durata anche se l'utente (o NTP) cambia l'ora di sistema?

per es.,

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?
}
È stato utile?

Soluzione

A partire dalla data di scrittura (Nov 2013), se il tempo cambia parete-orologio mentre si è in attesa su una variabile condizione di spinta, è sufficiente otterrà cattivi risultati.

Se non è necessario utilizzare spinta, è possibile utilizzare quello che viene chiamato "l'orologio monotona." Dal momento che l'orologio monotona non è influenzato da cambiamenti parete tempo-orologio, non è vulnerabile al problema che hai descritto. Si può aspettare tranquillamente 5 secondi utilizzando l'API pthread utilizzando qualcosa di simile a questo:

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

È possibile controllare l'attuazione di boost :: condition_variable. Forse si risolverà questo un giorno. L'implementazione è qui: http: //svn.boost. org / svn / boost / trunk / boost / thread / pthread / condition_variable.hpp

Altri suggerimenti

Credo che sia una condizione di competizione, anche se molto rara. L'attuazione di condition_variable :: TIMED_WAIT () per una durata converte semplicemente il valore di uno system_time utilizzando get_system_time () + wait_duration. Se le modifiche di tempo di sistema tra il momento get_system_time () viene chiamato, e l'ora di fine di attesa calcolato viene riconvertito ad un contatore tick-based per la chiamata del sistema operativo sottostante, il tempo di attesa sarà sbagliato.

Per testare questa idea, su Windows, ho scritto un semplice programma con un filo generando qualche uscita ogni 100 ms, in questo modo:

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

Un altro thread stava tramontando l'ora di sistema indietro di un minuto in passato ogni 100ms (questa discussione utilizza il livello di sistema operativo "sonno ()" chiamata che evita le conversioni al tempo di sistema):

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

Il primo thread, anche se dovrebbe uscita "Ping!" ogni 100 millisecondi, rinchiusi piuttosto rapidamente.

A meno che non mi manca qualcosa, sembra Boost non fornisce alcun API che evitano il problema di conversioni interne per l'ora del sistema, lasciando le applicazioni vulnerabili ai cambiamenti esterni all'orologio.

ho visto alcuni problemi con questo, se il processo utilizza anche i segnali. Io uso anche le variabili di condizione Boost con un tempo di durata.

Abbiamo un processo che utilizza un timer POSIX per avere tempi precisi a 20 Hz. Quando questo timer è attivato e il tempo è impostato su una precedente data / ora i blocchi variabili di condizione. Quando cambio l'indietro nel tempo al valore originale della variabile condizione continua.

Ho copiato l'attuazione da Boost e impostare la modalità di clock a CLOCK_MONOTONIC. Ora la variabile di condizione funziona correttamente anche se il tempo è cambiato.

Sarebbe stato utile se ci sarebbe stato la possibilità di impostare la modalità di una condizione variabile monotona, ma che non è possibile in questo momento.

emissione è stato fissato a 1,61 sviluppare filiale:

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top