I want to pretty much say "as long as we are under a certain time, continue to iterate"
the code for this looks like
int time = atoi(argv[1]);
auto start = std::chrono::high_resolution_clock::now();
while((std::chrono::duration_cast<chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count()) < time){
/*perform operation*/
}
However I am unable to compare against time like this and get the error error: conversion to ‘double’ from ‘std::chrono::duration<long int, std::ratio<1, 1000> >::rep {aka long int}’ may alter its value [-Werror=conversion]
does anyone know how to compare with the less than operator using chrono?
int time = atoi(argv[1]);
What units is time? seconds? nanoseconds? For this answer I'll assume seconds, but change it to whatever you need:
std::chrono::seconds time{atoi(arv[1])};
Next:
auto start = std::chrono::high_resolution_clock::now();
high_resolution_clock is going to be a type alias to either system_clock or steady_clock. The top of this answer explains the difference. I recommend chosing system_clock or steady_clock, depending on your needs, rather than letting the vendor choose for you.
while((std::chrono::duration_cast<chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count()) < time){
/*perform operation*/
}
Always try to stay within the chrono type system, instead of exiting it using .count(). Once you exit the chrono library, it can no longer help you. In this case it means doing the comparison using chrono units instead of ints.
When comparing chrono units, one does not need to cast such that both sides of the comparison are the same units. It is ok to compare seconds and milliseconds for example. chrono will do the comparison correctly, taking into account the different units.
I like to issue a function-scope using namespace std::chrono as I find repeated std::chrono:: overly verbose, making the code harder to read.
using namespace std::chrono;
seconds time{atoi(arv[1])};
auto start = steady_clock::now();
while(steady_clock::now() - start < time)
{
// perform operation
}
Or you can algebraically rearrange this:
while(steady_clock::now() < start + time)
{
// perform operation
}
Noticing the "constant" on the rhs, you can collect and rename that:
auto finish = steady_clock::now() + seconds{atoi(arv[1])};
while(steady_clock::now() < finish)
{
// perform operation
}
All of the above are equivalent, so you can choose whichever one you find more readable.
The error is in the precedence, you cast is performed after count() function, this cause that the cast is over a double value.
The problem can be solved in this way:
int time = atoi(argv[1]);
auto start = std::chrono::high_resolution_clock::now();
while(((std::chrono::duration_cast<chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start)).count()) < time){
/*perform operation*/
}
Related
I want to start a clock at the beginning of my program and use its elapsed time during the program to do some calculations, so the time should be in a int, long or double format. For example i want to calculate a debounce time but when i try it like this i get errors because the chrono high resolution clock is not in an int, long or double format and therefore i can't subtract 50ms from that (my debounceDelay) or save that value to a double (my lastDebounceTime). Originally i had a working Arduino Game (Pong) with an LCD and i want to convert this into a C++ console application.
On the Arduino there was this function "millis()" that gave me the runtime in ms and this worked perfectly fine. I can't find a similar function for C++.
double lastDebounceTime = 0;
double debounceDelay = 50;
void Player1Pos() {
if ((std::chrono::high_resolution_clock::now() - lastDebounceTime) > debounceDelay) {
if ((GetKeyState('A') & 0x8000) && (Player1Position == 0)) {
Player1Position = 1;
lastDebounceTime = std::chrono::high_resolution_clock::now();
}
else if ((GetKeyState('A') & 0x8000) && (Player1Position == 1)) {
Player1Position = 0;
lastDebounceTime = std::chrono::high_resolution_clock::now();
}
}
I am very new to C++ so any help is greatly appreciated.
Thank you all!
I find the question misguided in its attempt to force the answer to use "int, long, or double". Those are not appropriate types for the task at hand. For references, see A: Cast chrono::milliseconds to uint64_t? and A: C++ chrono - get duration as float or long long. The question should have asked about obtaining the desired functionality (whatever the code block is supposed to do), rather than asking about a pre-chosen approach to the desired functionality. So that is what I will answer first.
Getting the desired result
To get the code block to compile, you just have to drop the insistence that the variables be "int, long, or double". Instead, use time-oriented types for time-oriented data. Here are the first two variables in the code block:
double lastDebounceTime = 0;
double debounceDelay = 50;
The first is supposed to represent a point in time, and the second a time duration. The C++ type for representing a point in time is std::chrono::time_point, and the C++ type for a time duration is a std::chrono::duration. Almost. Technically, these are not types, but type templates. To get actual types, some template arguments need to be supplied. Fortunately, we can get the compiler to synthesize the arguments for us.
The following code block compiles. You might note that I left out details that I consider irrelevant to the question at hand, hence that I feel should have been left out of the minimal reproducible example. Take this as an example of how to simplify code when asking questions in the future.
// Use the <chrono> library when measuring time
#include <chrono>
// Enable use of the `ms` suffix.
using namespace std::chrono_literals;
std::chrono::high_resolution_clock::time_point lastDebounceTime;
// Alternatively, if the initialization to zero is not crucial:
// auto lastDebounceTime = std::chrono::high_resolution_clock::now();
auto debounceDelay = 50ms;
void Player1Pos() {
if ((std::chrono::high_resolution_clock::now() - lastDebounceTime) > debounceDelay) {
// Do stuff
lastDebounceTime = std::chrono::high_resolution_clock::now();
}
}
Subtracting two time_points produces a duration, which can be compared to another duration. The logic works and now is type-safe.
Getting the desired approach
OK, back to the question that was actually asked. You can convert the value returned by now() to an arithmetic type (integer or floating point) with the following code. You should doubts about using this code after reading the comment that goes with it.
// Get the number of [some time units] since [some special time].
std::chrono::high_resolution_clock::now().time_since_epoch().count();
The time units involved are not specified by the standard, but are instead whatever std::chrono::high_resolution_clock::period corresponds to, not necessarily milliseconds. The special time is called the clock's epoch, which could be anything. Fortunately for your use case, the exact epoch does not matter – you just need it to be constant for each run of the program, which it is. However, the unknown units could be a problem, requiring more code to handle correctly.
I find the appropriate types easier to use than trying to get this conversion correct. Especially since it required no change to your function.
I'm trying to update the basic dev library of my project from C++98 to C++11.
In the dev library, there are many functions about time, such as
uint64_t getCurrentMSTime()
{
struct timeval stv;
gettimeofday(&stv, NULL);
uint64_t ms = stv.tv_sec ;
ms = ms * 1000 + stv.tv_usec / 1000;
return ms;
}
I'm trying to change it with std::chrono of C++11.
For now it seems that I have two choices, one is to return time_point, the other is to return immediately std::chrono::milliseconds::rep
std::chrono::time_point<std::chrono::system_clock> getCurrentTime1() {
return std::chrono::system_clock::now();
}
std::chrono::milliseconds::rep getCurrentTime2() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
Well, I know that the first one is more flexible because it returns a time_point, which means that we can convert it into milliseconds, nanoseconds, seconds etc, whereas the second one is return only milliseconds.
But let's say that the developers use ONLY milliseconds so we can ignore the flexible issue.
In this case, which one is better?
BTW, the developers would do something like this: std::map<std::string, ???> mp;. So my code will decide the ??? part.
std::map<std::string, std::chrono::time_point<std::chrono::system_clock>> mp{std::string("abc"), getCurrentTime1()};
vs
std::map<std::string, std::milliseconds::rep> mp{std::string("abc"), getCurrentTime2()};.
Which one is better? Or are they almost the same?
I agree with the currently accepted answer that you should value type-safety, and not return an integral type. However I disagree that returning milliseconds is best.
Type safety applies to the difference between time points and time durations as well. For example it makes perfect sense to add two time durations. But it is nonsensical to add two time points, though you can subtract them yielding a time duration.
Since the meaning of getCurrentTime() is to return the current point in time, one should return a std::chrono::time_point. One can easily choose to return a time_point based on system_clock with milliseconds precision:
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
getCurrentTime()
{
return std::chrono::time_point_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now());
}
In C++20, there's a convenience type alias for this type to make it a little easier to spell. You could create such a type alias for yourself if you would like to get a head start on things:
std::chrono::sys_time<std::chrono::milliseconds>
getCurrentTime()
{
return std::chrono::time_point_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now());
}
Or you can create an even shorter name for use within your application, perhaps:
using MSTime = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
...
MSTime
getCurrentMSTime()
{
return std::chrono::time_point_cast<MSTime::duration>(
std::chrono::system_clock::now());
}
You certainly don't want to throw away the type information that <chrono> offers. If you convert the time_point you get from the system clock into an integral value right away, you can equally well keep the legacy function as it is.
Instead, decide upfront whether you want to handle points in time relative to the epoch or not. The old function suggests that you want this, so your function should look like this;
std::chrono::milliseconds getDurationSinceEpoch()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
}
But let's say that the developers use ONLY milliseconds so we can ignore the flexible issue
Don't. What you get is here is for free. Whenever this requirement changes, and some developer mixes getDurationSinceEpoch() return values with durations in whatever resolution, it becomes quite brittle. By baking the correct units into your functions, you guard against future bugs.
Last, you want your map to have this signature:
std::map<std::string, std::chrono::milliseconds>
Suppose I want to call my_func() periodically at CALL_PERIOD intervals
auto last_call_time = CHRONO_NEGATIVE_INFINITY;
while (true)
{
if (std::chrono::system_clock::now() - last_call_time > CALL_PERIOD)
{
last_call_time = std::chrono::system_clock::now();
my_func();
}
}
What would be an appropriate CHRONO_NEGATIVE_INFINITY such that the line
std::chrono::system_clock::now() - last_call_time > CALL_PERIOD
will always evaluate true on the first run?
I've tried time_point::min() but that doesn't seem to work
One of the main reasons to have a type like std::optional is so that we don't have to have hacks like picking a specific value to mean "not a value":
std::optional<std::chrono::system_clock::time_point> last_call_time;
while (true)
{
auto curr = std::chrono::system_clock::now()
if (!last_call_time || (curr - *last_call_time) > CALL_PERIOD)
{
last_call_time = std::chrono::system_clock::now();
my_func();
}
}
If C++17 is not available to you, and/or you're just dead-set on using the old hack of picking a special value, you can get the clock's rep type and compute the minimum possible integer of it:
using sys_clock = std::chrono::system_clock;
constexpr auto min_int = std::numeric_limits<sys_clock::rep>::min();
constexpr sys_clock::duration min_duration(min_int);
sys_clock::time_point min_time(min_duration);
Of course, min_time is still a valid time, so it's unlike any "infinity" representation for floats.
The rationale that there is no time_point::infinity equivalent is that time_points are simple wrappers around arithmetic types. Simplistic wrappers lead to the highest performing code. And this same rationale is also a clue that for special cases, time_point::infinity actually does exist!
Let me elaborate further on that entirely confusing first paragraph...
system_clock::time_point is a simple wrapper around a duration. Exactly which duration is unspecified, but let's just say it is nanoseconds. And nanoseconds is a simple wrapper around a 64 bit signed integer (say long long).
long long has no representation of +/- INFINITY. But it does have a minimum value: -9223372036854775808.
A shortcut for putting this value into a duration (say nanoseconds) is nanoseconds::min(), and a shortcut to putting this value into system_clock::time_point is system_clock::time_point::min().
However when you do so, it is an invitation for plain old signed integral overflow. After all:
cout << (10 - numeric_limits<long long>::min() > 1) << '\n';
overflows and prints out 0 (false). And that's precisely why:
auto CHRONO_NEGATIVE_INFINITY = system_clock::time_point::min();
didn't work.
There are several ways to get your code to work. Which is best for your application is up to you. But now that <chrono> is just a little less mysterious, you can better make that decision.
Perhaps the easiest way is to set CHRONO_NEGATIVE_INFINITY to something that isn't quite so negative so that you don't risk overflow:
auto CHRONO_NEGATIVE_INFINITY = std::chrono::system_clock::now() - CALL_PERIOD;
C++20 standardizes the existing practice that system_clock's epoch is 1970-01-01, so here's another possibility (that works back to C++11):
// Set CHRONO_NEGATIVE_INFINITY to 1970-01-01 00:00:00 UTC
auto CHRONO_NEGATIVE_INFINITY = std::chrono::system_clock::time_point{};
But let's say that for some reason you really, really need a time_point that is infinitely in the past. You can do that too, it just takes a little more work. float and double are arithmetic types too, and they do have a representation of INFINITY! So you can just build a time_point out of one of those types.
using dsec = std::chrono::duration<double>;
using tp_dsec = std::chrono::time_point<std::chrono::system_clock, dsec>;
auto CHRONO_NEGATIVE_INFINITY = tp_dsec{dsec{-INFINITY}};
The first line makes dsec a name for double-based-seconds. The second line makes tp_dsec a name for a system_clock-based time_point using dsec as its representation. And then the third line just stuffs negative infinity into a tp_dsec. The rest of your code will implicitly convert to double-based time_points and durations when doing the test.
If you rewrite your test like this:
auto last_call_time = std::chrono::system_clock::min();
...
if (std::chrono::system_clock::now() - CALL_PERIOD > last_call_time)
you shouldn't overflow.
Use 0:
std::chrono::duration CALL_PERIOD(std::chrono::seconds(2));
std::chrono::steady_clock::time_point last_call_time; //auto init to 0,
// or can use explicit initialization to 0:
// std::chrono::steady_clock::time_point last_call_time(std::chrono::seconds(0));
while (true)
{
auto now = std::chrono::steady_clock::now();
if (now - last_call_time > CALL_PERIOD)
{
last_call_time = now;
my_func();
}
}
How can one multiply a chrono timepoint by a scalar? It works for durations, but timepoints can't be multiplied by a scalar ("error: invalid operands to binary expression").
Context:
I have some code that in real life will run for a long time. For testing purposes, I want to be able to speed it up by a factor, so everything happens similarly, but just in fast forward.
I thought of making my own ScaledClock class, that returns values from chrono::steady_clock, but with a scaling parameter that can be set to something greater than 1 to achieve a speed up. Here is some code:
steady_clock::time_point ScaledClock::now() {
return steady_clock::now() * speedUp; // <--- error
}
void ScaledClock::sleep_for(steady_clock::duration duration) {
std::this_thread::sleep_for(duration / speedUp);
}
void ScaledClock::sleep_until(steady_clock::time_point time) {
std::this_thread::sleep_until(time / speedUp); // <--- error
}
If the speedUp is 2, for instance, then the program will always think that twice as much time has passed. It will also sleep for half as long. As long as I am disciplined about not using this class for all timing, I think it should work.
(Alternatively, if someone has a much better way of achieving this, I'd love to hear it).
Edit: copy of comment, because I think it is useful clarification:
en.cppreference.com/w/cpp/chrono/time_point:
Class template std::chrono::time_point represents a point in time. It
is implemented as if it stores a value of type Duration indicating the
time interval from the start of the Clock's epoch.
So I want all the times since the epoch doubled. If the epoch is not start of program execution, and my code happens to think that it is running in 4036, I'm not really bothered
You will need to store a starting point (now() e.g. at program start) and then determine the time passed since that starting point as a duration. You can then add this duration multiplied with your factor to the start point and return it as time point in your ScaledClock::now() function. Just like this:
#include <chrono>
#include <unistd.h>
int main() {
auto start = std::chrono::steady_clock::now();
sleep(1);
auto actualNow = std::chrono::steady_clock::now();
auto timePassed = actualNow - start;
auto timePassedScaled = timePassed * 2.0;
auto scaledNow = start + timePassedScaled;
return 0;
}
I'm using OpenCV to write a video file. For cv::VideoWriter to work correctly the call to the write() function has to happen exactly 30 times per second (for a 30fps video).
I found this code which uses the boost library to achieve this. I want to to the same but using std::chrono in my program. This is my implementation:
std::chrono::high_resolution_clock::time_point prev = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::time_point current = prev;
long long difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
while(recording){
while (difference < 1000000/30){
current = std::chrono::high_resolution_clock::now();
difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
}
theVideoWriter.write(frameToRecord);
prev = prev + std::chrono::high_resolution_clock::duration(1000000000/30);
difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
}
theVideoWriter.release();
I'm not sure if thats the correct way to do this or if there is a more efficient way. Is there anything better than casting the duration to long long difference?
There is a basic tenant to working with chrono, which goes something like:
If you use count(), and/or you have conversion factors in your
chrono code, then you're trying too hard.
This is not your fault. There really is no good chrono tutorial and that is my bad, and I've recently decided I need to do something about that.
In your case, I recommend rewriting your code along the lines of the following:
First create a duration unit which represents the period of your frame rate:
using frame_period = std::chrono::duration<long long, std::ratio<1, 30>>;
Now when you say frame_period{1}, that means exactly 1/30 of a second.
The next thing to note is that chrono comparisons are always exact, as long as you stay in the chrono system. count() is a "trap door" for escaping out of the chrono system. Only escape out when you have no other choice. So...
auto prev = std::chrono::high_resolution_clock::now();
auto current = pref;
// Just get the difference, and don't worry about the units for now
auto difference = current-prev;
while(recording)
{
// Find out if the difference is less than one frame period
// This comparison will do all the conversions for you to get an exact answer
while (difference < frame_period{1})
{
current = std::chrono::high_resolution_clock::now();
// stay in "native units"...
difference = current-prev;
}
theVideoWriter.write(frameToRecord);
// This is a little tricky...
// prev + frame_period{1} creates a time_point with a complicated unit
// Use time_point_cast to convert (via truncation towards zero) back to
// the "native" duration of high_resolution_clock
using hr_duration = std::chrono::high_resolution_clock::duration;
prev = std::chrono::time_point_cast<hr_duration>(prev + frame_period{1});
// stay in "native units"...
difference = current-prev;
}
theVideoWriter.release();
The comments above are overly verbose once you get chrono. There's more comment than code above. But the above just works as you intended, with no need for "escaping out" of the chrono system.
Update
If you would want to initialize difference such that the inner loop won't be executed the first time, you could initialize it to something just over frame_period{1} instead of to 0. To do this, the utilities found here come in handy. Specifically ceil:
// round up
template <class To, class Rep, class Period>
To
ceil(const std::chrono::duration<Rep, Period>& d)
{
To t = std::chrono::duration_cast<To>(d);
if (t < d)
++t;
return t;
}
ceil is a replacement for duration_cast that will round up when the conversion is inexact, as opposed to truncate towards zero. Now you can say:
auto difference = ceil<hr_duration>(frame_period{1});
And you are guaranteed that difference >= frame_period{1}. Furthermore, it is known in practice that the duration of high_resolution_clock is nanoseconds, thus you can deduce (or test) that difference is actually initialized to 33,333,334ns, which is 2/3 of a nanosecond greater than 1/30 of a second, which equals frame_period{1}, which equals 33,333,333+1/3ns.