C++ chrono library on Raspberry Pi

1.5k views Asked by At

On a Raspberry Pi 2, I need to call a php file on a regular basis, typically every 100ms. I found this c++ code which looks like it does what I need and a test version of it compiles and runs fine using CodeBlock on Windows. I've updated the wheezy RPi with C++ libraries from jessie using this guide, compiled it on the Pi using g++-4.9 -std=c++14, but I get no output. I'm very new to Linux and C++ so any help will be appreciated. Code is as follows

#include <iostream>
#include <cstdlib>
#include <chrono>
using namespace std;

int main () {
    using frame_period = std::chrono::duration<long long, std::ratio<50, 100>>;
    auto prev = std::chrono::high_resolution_clock::now();
    auto current = prev;
    auto difference = current-prev;
    while(true)
    {
        while (difference < frame_period{1})
        {
            current = std::chrono::high_resolution_clock::now();
            difference = current-prev;
        }
        //cout << std::system("php run.php");
        std::cout << "OK ";
        using hr_duration = std::chrono::high_resolution_clock::duration;
        prev = std::chrono::time_point_cast<hr_duration>(prev + frame_period{1});
        difference = current-prev;
    }
return 0;
}

Is my problem likely to be with one of the libraries, or something else in the code? I'm not even sure that this is the best way to achieve what I'd like, as the code when running looks like it ties up the processor in the loop.

1

There are 1 answers

1
Jonathan Wakely On BEST ANSWER

The problem is the the output is being buffered by the stdio library, you need to flush the output stream to make it appear immediately:

    std::cout << "OK " << std::flush;

Your solution is very inefficient because it does a busy loop, constantly re-checking the system time between intervals.

I would use a single call to get the time, and then this_thread::sleep_until() to make the program block until you want to run the script again:

#include <iostream>
#include <cstdio>
#include <chrono>
# include <thread>

int main()
{
  std::chrono::milliseconds period(100);
  auto next = std::chrono::high_resolution_clock::now() + period;
  while (true)
  {
    std::this_thread::sleep_until(next);
    next += period;
    // std::system("php run.php");
    std::cout << "OK " << std::flush;
  }
}

Since you're using C++14 you could also use the operator""ms literal to simplify the declaration of period:

using namespace std::literals::chrono_literals;
auto period = 100ms;

Or, more similar to the answer you found, instead of using a variable that represents 100ms you can define a type that represents that duration and then add units of that type (instead of 100 units of type milliseconds) to the next value:

// a type that represents a duration of 1/10th of a second
using period = std::chrono::duration<long, std::ratio<1, 10>>;
auto next = std::chrono::high_resolution_clock::now() + period(1);
while (true)
{
  std::this_thread::sleep_until(next);
  next += period(1);
  ...
}