chrono with different time periods?

[亡魂溺海] 提交于 2019-12-11 04:56:40

问题


Currently I am using boost::rational<std::uint64> to keep track in my application.

Basically I have a clock that runs over a very long period of time and will be tick by different components of different time resolutions, e.g. 1/50s, 1/30s, 1001/30000s etc... I want to maintain perfect precision, i.e. no floating point. boost::rational works well for this purpose, however I think it would be better design to use std::chrono::duration for this.

My problem though is, how can I use std::chrono::duration here? Since it uses a compile time period I don't quite see how I can use it in my scenario where I need to maintain precision?


回答1:


You're allowed to set the period to 1 and use a floating point type for Rep.

I suspect that you can do the same thing with boost::rational, but you'll have to look quite closely at std::chrono, which I haven't done. Look at treat_as_floating_point and duration_values. Also try to figure out what the standard means by "An arithmetic type or a class emulating an arithmetic type".

One might reasonably argue that if boost::rational doesn't emulate an arithmetic type, then it's not doing its job. But it doesn't necessarily follow that it really does everything std::chrono::duration expects.




回答2:


If I'm understanding your question, and if you know all of the different time resolutions at compile-time, then the following will do what you want. You can figure out the correct tick period by using common_type on all of your different time resolutions as shown below:

#include <cstdint>
#include <chrono>

struct clock
{
    typedef std::uint64_t                      rep;
    typedef std::common_type
    <
        std::chrono::duration<rep, std::ratio<1, 50>>,
        std::chrono::duration<rep, std::ratio<1, 30>>,
        std::chrono::duration<rep, std::ratio<1001, 30000>>
    >::type                                    duration;
    typedef duration::period                   period;
    typedef std::chrono::time_point<clock>     time_point;
    static const bool is_steady =              true;

    static time_point now()
    {
        // just as an example
        using namespace std::chrono;
        return time_point(duration_cast<duration>(steady_clock::now().time_since_epoch()));
    }
};

This will compute at compile-time the largest tick period which will exactly represent each of your specified resolutions. For example with this clock one can exactly represent:

  • 1/50 with 600 ticks.
  • 1/30 with 1000 ticks.
  • 1001/30000 with 1001 ticks.

The code below exercises this clock and uses the "chrono_io" facility described here to print out not only the run-time number of ticks of your clock, but also the compile-time units of your clock-tick:

#include <iostream>
#include <thread>
#include "chrono_io"

int main()
{
    auto t0 = clock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    auto t1 = clock::now();
    std::cout << (t1-t0) << '\n';
}

For me this prints out:

633 [1/30000]seconds

Meaning: There were 633 clock ticks between calls to now() and the unit of each tick is 1/30000 of a second. If you don't want to be beholden to "chrono_io" you can inspect the units of your clock with clock::period::num and clock::period::den.

If your different time resolutions are not compile-time information, then your current solution with boost::rational is probably best.



来源:https://stackoverflow.com/questions/12787544/chrono-with-different-time-periods

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!