I am a beginner to C , trying to improve my skills by working on a project. I am trying to have my program call a certain function 100 times a second for 30 seconds. I thought that this would be a common, well documented problem but so far I did not manage to find a solution. Could anyone provide me with an implementation example or point me towards one?
Notes: my program is intended to be single-threaded and to use only the standard library.
CodePudding user response:
There are two reasons you couldn't find a trivial answer:
- This statement "I am trying to have my program call a certain function 100 times a second for 30 seconds" is not well-defined.
- Timing and scheduling is a very complication problem.
In a practical sense, if you just want something to run approximately 100 times a second for 30 seconds, assuming the function doesn't take long to run, you can say something like:
for (int i=0;i<3000;i ) {
do_something();
this_thread::sleep_for(std::chrono::milliseconds(10));
}
This is an approximate solution.
Problems with this solution:
- If do_something() takes longer than around 0.01 milliseconds your timing will eventually be way off.
- Most operating systems do not have very accurate sleep timing. There is no guarantee that asking to sleep for 10 milliseconds will wait for exactly 10 milliseconds. It will usually be approximately accurate.
CodePudding user response:
You can use std::this_thread::sleep_until
and calculate the end time of the sleep according to desired frequency:
void f()
{
static int counter = 0;
std::cout << counter << '\n';
counter;
}
int main() {
using namespace std::chrono_literals;
using Clock = std::chrono::steady_clock;
constexpr auto sleepTime = std::chrono::duration_cast<std::chrono::milliseconds>(1s) / 100; // conversion to ms needed to prevent truncation in integral division
constexpr auto repetitions = 30s / sleepTime;
auto const start = Clock::now();
for (std::remove_const_t<decltype(repetitions)> i = 1; i <= repetitions; i)
{
f();
std::this_thread::sleep_until(start sleepTime * i);
}
}
Note that this code will not work, if f()
takes more than 10ms.
CodePudding user response:
You can't time it perfectly, but you can try like this:
using std::chrono::steady_clock;
using namespace std::this_thread;
auto running{ true };
auto frameTime{ std::chrono::duration_cast<steady_clock::duration>(std::chrono::duration<float>{1.0F / 100.0F}) }
auto delta{ steady_clock::duration::zero() };
while (running) {
auto t0{ steady_clock::now() };
while (delta >= frameTime) {
call_your_function(frameTime);
delta -= frameTime;
}
if (const auto dt{ delta steady_clock::now() - t0 }; dt < frameTime) {
sleep_for(frameTime - dt);
delta = steady_clock::now() - t0;
}
else {
delta = dt;
}
}