Counter Thread "wait_for" condition Verständisproblem



  • Guten Morgen Leute.

    ich haben folgenden Code-Schnipsel 🙂

    std::mutex counterMtx;
       std::atomic<int> counter;
       std::condition_variable cv;
    
       /* loop func */
       auto freqCounterFunc = [](std::mutex& tCounterMtx, std::condition_variable& tCv, std::atomic<int>& tCounter)
       {
           std::unique_lock<std::mutex> lck(tCounterMtx);
    
           std::cout << "Start counter loop" << "\n";
    
           /* stay in loop unti condition is set (form outside) */
           while (tCv.wait_for(lck, std::chrono::seconds(1)) == std::cv_status::timeout)
           {
               /* count per second => Hz */
               auto currentvalue = tCounter.exchange(0);
               
               std::cout << currentvalue <<  " Hz" << std::endl;
           }
    
           std::cout << "End counter loop" << "\n";
       };
    
       /* run hz measure thread */
       thread freqCounter(freqCounterFunc, std::ref(counterMtx), std::ref(cv), std::ref(counter));
    
       // TODO HERE: other thread count the atomic "counter"
    
       /* wait for exit */
       std::cout << "wait for exit loop" << "\n";
       getchar();
    
       /* exit loop*/
       cv.notify_one();
       /* thread done */
       freqCounter.join();
    

    ich habe einen Thread, welcher eine loop enthält , die jede sekunde einen counter ausgibt. Sprich via einer wait_for condition geh ich jede Sekunden in den timeout und gebe was aus.
    Wenn ich nun den Thread beenden will, setze ich die wait-condition (press key) , so dass er die loop verlässt... so meine Denkweiße.

    Aber der thread bzw. die loop durchfläuft "exakt" die loop 2 mal und beenden sich , ohne dass ich ne Eingabe mache

    Ausgabe:

    wait for exit loop
    Start counter loop
    0 Hz
    0 Hz
    End counter loop
    

    habe ich mit der wait_condition was falsch verstanden !?:) geht das vll. anderes einfach etc.?;

    danke schonmal für euere Hilfge



  • https://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
    benutze den zweiten overload.

    wait_for(lock, 1s, [](){ return doAbort; } (doAbort hier ein bool den du mitträgst. Auf der anderen seite setzt du den dann auf true und machst dein notify. der bool muss von dem selben mutex geschützt werden den die condition variable benutzt via den unique_lock.)

    condition_variables können sporadisch aktiviert werden. (als wenn ein geister notify_one zufällig aufegrufen würde. deswegen wenn du dich auf deine notifis verlassen willst immer an eine bedingung knüpfen)



  • @5cript sagte in Counter Thread "wait_for" condition Verständisproblem:

    condition_variables können sporadisch aktiviert werden. (als wenn ein geister notify_one zufällig aufegrufen würde. deswegen wenn du dich auf deine notifis verlassen willst immer an eine bedingung knüpfen)

    Hi Script danke für deine Antwort, werde so wie du beschrieben hast mal versuchen.

    ABER: wie kommt es dass es ein "geister" sporadeische notify geeben kann, das verstehe ich jetzt nich!?

    EDIT: aber irgendwie finde ich die /meine Lösung zu "komplziert" könnte man das einfacher machen?;)



  • Hier ist Information zu spurious wakeups:
    https://en.wikipedia.org/wiki/Spurious_wakeup

    hast du jthread? (C++20), hier musst du aber dein zeit handling selber machen:

    std::jthread bla = [](std::stop_token token) {
      while (!token.stop_requested()) {
         /*...*/
      }
    };
    
    bla.request_stop();
    bla.join();
    

    sonst, das würde ich tun:

    std::promise<void> p;
    std::thread freqThread = [f = p.get_future()](){
      while(f.wait_for(1s) != std::future_status::ready) {
        // your code
      }
    };
    p.set_value(); // stop thread.
    

    Und das wrappen in einer Klasse.

    EDIT: Ich bin mir nicht sicher wie stabil das ist, wenn du hohe frequenzen messen willst. Würde mal in Frage stellen ob das so eine optimale Lösung ist. Wobei man jeenseits von nicht-echtzeit systemen da glaube ich sowieso nicht so viel chancen hat. ggf solltest du keinen parallelen thread laufen lassen sondern einfach gegen die clock checken und errechnen (std::chrono::high_resolution_clock oder nativen möglichkeiten)


Anmelden zum Antworten