2013-07-08 10 views
6

Ho usato gcc-4.8.1 (configura: ./configure --prefix =/usr/local) per compilare il codice seguente in Ubuntu 12.04, ma quando l'ho eseguito, non ha funzionato. non si è fermato ad aspettare il mutex. Ha restituito false e ha generato "Hello world!"Perché std :: timed_mutex :: try_lock_for non funziona?

comando: g ++ -std = C++ 11 main.cpp -omain -pthread

Quando usato gcc-4.6 (apt-get install g ++) per compilare, ha funzionato bene. Il programma ha atteso circa dieci secondi e ha prodotto "Hello world!"

#include <thread> 
#include <iostream> 
#include <chrono> 
#include <mutex> 

std::timed_mutex test_mutex; 

void f() 
{ 
    test_mutex.try_lock_for(std::chrono::seconds(10)); 
    std::cout << "hello world\n"; 
} 

int main() 
{ 
    std::lock_guard<std::timed_mutex> l(test_mutex); 
    std::thread t(f); 
    t.join(); 
     return 0; 
} 

risposta

6

Se non mi sbaglio, che è Bug 54562 -mutex and condition variable timers.

Il motivo per il bug è anche menzionato:

Questo è perché utilizza l'orologio CLOCK_MONOTONIC (se disponibili sulla piattaforma ) per calcolare il tempo assoluto quando è necessario tornare, che non è corretto come la chiamata pthread_mutex_timedlock() POSIX utilizza l'orologio CLOCK_REALTIME e sulla mia piattaforma l'orologio monotonico è molto indietro rispetto all'orologio in tempo reale.

Tuttavia, questo non spiega perché si vede il comportamento corretto su gcc-4.6. Forse _GLIBCXX_USE_CLOCK_MONOTONIC non è abilitato?

+0

Grazie, quando disattivo _GLIBCXX_USE_CLOCK_MONOTONIC, gcc-4.8 e gcc-4.6 hanno lo stesso comportamento. E penso che il motivo per cui hanno un comportamento diverso è questo marco. – miskcoo

+1

Per chiunque voglia aggiornare gcc/g ++ a 4.9 (dove è stato corretto il bug), quindi seguire [queste istruzioni] (http://superuser.com/a/394811/235047) per Ubuntu, sostituendo semplicemente '4.6' con '4.9'. – Garrett

+0

Come abilitare _GLIBCXX_USE_CLOCK_MONOTONIC? – SomethingSomething

0

Una possibile soluzione:

const int WAIT_PRECISION_MS = 10; // Change it to whatever you like 
int TIME_TO_WAIT_MS = 2000;  // Change it to whatever you like 
int ms_waited = 0; 
bool got_lock = false; 
while (ms_waited < TIME_TO_WAIT_MS) { 
    std::this_thread::sleep_for(
          std::chrono::milliseconds(WAIT_PRECISION_MS)); 
    ms_waited += WAIT_PRECISION_MS; 
    got_lock = YOUR_MUTEX.try_lock(); 
    if (got_lock) { 
     break; 
    } 
} 

Il WAIT_PRECISION_MS vi dirà il ciclo while quanto spesso a "svegliarsi" e provare a ottenere il blocco. Ma direbbe anche quanto accurata sarà la tua scadenza, a meno che il tuo tempo di precisione non sia un fattore del tempo limite.

Ad esempio:

termine = 20, precisione = 3: 3 non è un fattore 20 - l'ultima iterazione del ciclo, mentre sarà quando ms_waited è 18. Ciò significa che siete aspettando un totale di 21ms e non di 20ms.

termine = 20, precisione = 4: 4 è un fattore 20 - l'ultima iterazione del ciclo, mentre sarà quando ms_waited è 16. Ciò significa che si sta andando ad aspettare esattamente 20ms, come il tuo termine è definito.

Problemi correlati