Arkathorn
Arkathorn

Reputation: 69

Proper method of using std::chrono

While I realize this is probably one of many identical questions, I can't seem to figure out how to properly use std::chrono. This is the solution I cobbled together.

#include <stdlib.h>
#include <iostream>
#include <chrono>

typedef std::chrono::high_resolution_clock Time;
typedef std::chrono::milliseconds ms;

float startTime;

float getCurrentTime();

int main () {
    startTime = getCurrentTime();
    std::cout << "Start Time: " << startTime << "\n";

    while(true) {
        std::cout << getCurrentTime() - startTime << "\n";
    }

    return EXIT_SUCCESS;
}

float getCurrentTime() {
    auto now = Time::now();
    return std::chrono::duration_cast<ms>(now.time_since_epoch()).count() / 1000;
}

For some reason, this only ever returns integer values as the difference, which increments upwards at rate of 1 per second, but starting from an arbitrary, often negative, value.

What am I doing wrong? Is there a better way of doing this?

Upvotes: 5

Views: 21892

Answers (3)

user28462484
user28462484

Reputation: 1

This is basic Stopwatch sample code, when you press enter it will stop the time.

It can give you kind of a grasp of what you can do with chrono.

#include <iostream>
#include <chrono>
#include <thread>
#include <algorithm>
using namespace std::chrono;

int main()
{
    auto start = std::chrono::high_resolution_clock::now();
    std::this_thread::sleep_for(0s);
    std::cout << "press enter to stop time \n";
    std::cin.get();
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<float> duration = end - start;
    std::cout << "your time was " << duration.count() << "s " << std::endl;
    return 0;
}

Upvotes: -2

Richard Hodges
Richard Hodges

Reputation: 69854

This program does a similar thing. Hopefully it shows some of the capabilities (and methodology) of std::chrono:

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

int main()
{
    using namespace std::literals;
    namespace chrono = std::chrono;
    using clock_type = chrono::high_resolution_clock;

    auto start = clock_type::now();

    for(;;) {
        auto first = clock_type::now();

        // note use of literal - this is c++14
        std::this_thread::sleep_for(500ms);

        // c++11 would be this:
        //        std::this_thread::sleep_for(chrono::milliseconds(500));

        auto last = clock_type::now();
        auto interval = last - first;
        auto total = last - start;

        // integer cast
        std::cout << "we just slept for " << chrono::duration_cast<chrono::milliseconds>(interval).count() << "ms\n";

        // another integer cast
        std::cout << "also known as " << chrono::duration_cast<chrono::nanoseconds>(interval).count() << "ns\n";

        // floating point cast
        using seconds_fp = chrono::duration<double, chrono::seconds::period>;
        std::cout << "which is " << chrono::duration_cast<seconds_fp>(interval).count() << " seconds\n";

        std::cout << "  total time wasted: " << chrono::duration_cast<chrono::milliseconds>(total).count() << "ms\n";
        std::cout << "         in seconds: " << chrono::duration_cast<seconds_fp>(total).count() << "s\n";


        std::cout << std::endl;
    }
    return 0;
}

example output:

we just slept for 503ms
also known as 503144616ns
which is 0.503145 seconds
  total time wasted: 503ms
         in seconds: 0.503145s

we just slept for 500ms
also known as 500799185ns
which is 0.500799 seconds
  total time wasted: 1004ms
         in seconds: 1.00405s

we just slept for 505ms
also known as 505114589ns
which is 0.505115 seconds
  total time wasted: 1509ms
         in seconds: 1.50923s

we just slept for 502ms
also known as 502478275ns
which is 0.502478 seconds
  total time wasted: 2011ms
         in seconds: 2.01183s

Upvotes: 5

Howard Hinnant
Howard Hinnant

Reputation: 218700

  • Don't escape the chrono type system until you absolutely have to. That means don't use .count() except for I/O or interacting with legacy API.

This translates to: Don't use float as time_point.

  • Don't bother with high_resolution_clock. This is always a typedef to either system_clock or steady_clock. For more portable code, choose one of the latter.

.

#include <iostream>
#include <chrono>

using Time = std::chrono::steady_clock;
using ms = std::chrono::milliseconds;

To start, you're going to need a duration with a representation of float and the units of seconds. This is how you do that:

using float_sec = std::chrono::duration<float>;

Next you need a time_point which uses Time as the clock, and float_sec as its duration:

using float_time_point = std::chrono::time_point<Time, float_sec>;

Now your getCurrentTime() can just return Time::now(). No fuss, no muss:

float_time_point
getCurrentTime() {
    return Time::now();
}

Your main, because it has to do the I/O, is responsible for unpacking the chrono types into scalars so that it can print them:

int main () {
    auto startTime = getCurrentTime();
    std::cout << "Start Time: " << startTime.time_since_epoch().count() << "\n";

    while(true) {
        std::cout << (getCurrentTime() - startTime).count() << "\n";
    }
}

Upvotes: 24

Related Questions