2017-12-07 3 views
1

Ich versuche, eine Art Thread-Pool in C++ zu schreiben. Der Code funktioniert gut in OSX, aber unter Linux habe ich ein seltsames Verhalten. Nach ein bisschen Debugging habe ich festgestellt, dass das Problem auf einen Aufruf von std :: condition_variable :: wait_until zurückzuführen ist, was ich falsch machen muss.C++ wait_until seltsames Timeout-Verhalten

Mit dem folgenden Code Ich erwarte, dass die Schleife einmal alle drei Sekunden geschleift werden:

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

using namespace std; 

typedef std::chrono::steady_clock       my_clock; 
typedef std::chrono::duration<float, std::ratio<1> >  seconds_duration; 
typedef std::chrono::time_point<my_clock, seconds_duration> timepoint; 

timepoint my_begin = my_clock::now(); 

float timepointToFloat(timepoint time) { 
    return time.time_since_epoch().count() - my_begin.time_since_epoch().count(); 
} 

void printNow(std::string mess) { 
    timepoint now = my_clock::now(); 
    cout << timepointToFloat(now) << " " << mess << endl;; 
}; 

void printNow(std::string mess, timepoint time) { 
    timepoint now = my_clock::now(); 
    cout << timepointToFloat(now) << " " << mess << " " << timepointToFloat(time) << endl;; 
}; 

int main() { 
    mutex _global_mutex; 
    condition_variable _awake_global_execution; 
    auto check_predicate = [](){ 
    cout << "predicate called" << endl; 
    return false; 
    }; 

    while (true) { 
    { // Expected to loop every three seconds 
     unique_lock<mutex> lock(_global_mutex); 
     timepoint planned_awake = my_clock::now() + seconds_duration(3); 
     printNow("wait until", planned_awake); 
     _awake_global_execution.wait_until(lock, planned_awake, check_predicate); 
    } 
    printNow("finish wait, looping"); 
    } 

    return 0; 
} 

Aber manchmal ich als Ausgabe erhalten:

<X> wait until <X+3> 
predicate called 
(...hangs here for a long time) 

(wobei X eine Zahl ist), Es scheint also, dass die Zeitüberschreitung nach drei Sekunden nicht geplant ist. Manchmal bekomme ich stattdessen:

<X> wait until <X+3> 
predicate called 
predicate called 
<X> finish wait, looping 
<X> wait until <X+3> (another loop) 
predicate called 
predicate called 
<X> finish wait, looping 
(...continue looping without waiting) 

so scheint es das Timeout nach einem kleinen Bruchteil von Sekunden geplant ist. Ich denke, dass ich etwas mit dem Timeout-Zeitpunkt vermasselt habe, aber ich kann nicht herausfinden, was ich falsch mache.

Wenn es relevant sein kann, funktioniert dieser Code gut in OSX, während in Linux (Ubuntu 16.04, gcc 5.4, kompiliert mit "g ++ main.cc -std = C++ 11 -thread") ich die seltsames Verhalten.

Wie kann ich es funktionieren lassen?

+0

Bevor Sie warten, müssen Sie für das, was Sie warten, um sicherzustellen, nicht bereits geschehen ist. Und bevor Sie sich entscheiden, nicht zu warten, müssen Sie sicherstellen, dass das, worauf Sie warten, bereits passiert ist. Zustandsvariablen sind zustandslos und haben keine Ahnung, worauf Sie warten oder ob es passiert ist. Es ist deine Aufgabe, den Überblick zu behalten. –

+0

Haben Sie versucht, Ihr Zeitlimit auf Ihre Uhr-Dauer zu setzen? 'Std :: chrono :: duration_cast (sekunden_dauer (3))' –

Antwort

0

Versuchen Sie Timeout auf Ihre Uhr der Dauer würfen

auto planned_awake = my_clock::now() + 
        std::chrono::duration_cast<my_clock::duration>(secon‌​ds_duration(3)); 
+0

Danke, das funktioniert !! Ich habe vorher versucht, es wie folgt zu übertragen: "Zeitpunkt geplante_awake = my_clock :: jetzt() + std :: chrono :: duration_cast (secon ds_duration (3));" aber es machte keinen Unterschied. Stattdessen wird das Schlüsselwort auto anstelle des Zeitpunkts verwendet. Aber warum? – stavoltafunzia

+0

Ich bin mir nicht sicher, aber obwohl das Manipulieren verschiedener Dauern gut funktioniert und scheitert, indem man Konvertierungen einschränkt, sind time_points nicht so empfindlich. Es funktioniert, wenn Sie "amy_clock :: time_point" verwenden. –