aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src/Stopwatch.cpp
blob: 550f1ebd800d46ccf98ce54c21adfc9aa3f5ffed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "Stopwatch.h"
#include "vcpkg_Checks.h"

namespace vcpkg
{
    Stopwatch Stopwatch::createUnstarted()
    {
        return Stopwatch();
    }

    Stopwatch Stopwatch::createStarted()
    {
        return Stopwatch().start();
    }

    bool Stopwatch::isRunning() const
    {
        return this->m_isRunning;
    }

    const Stopwatch& Stopwatch::start()
    {
        Checks::check_exit(!this->m_isRunning, "This stopwatch is already running.");
        this->m_isRunning = true;
        this->m_startTick = std::chrono::high_resolution_clock::now();
        return *this;
    }

    const Stopwatch& Stopwatch::stop()
    {
        auto tick = std::chrono::high_resolution_clock::now();
        Checks::check_exit(this->m_isRunning, "This stopwatch is already stopped.");
        this->m_isRunning = false;
        this->m_elapsedNanos += tick - this->m_startTick;
        return *this;
    }

    Stopwatch& Stopwatch::reset()
    {
        this->m_elapsedNanos = std::chrono::nanoseconds();
        this->m_isRunning = false;
        return *this;
    }

    std::string Stopwatch::toString() const
    {
        using std::chrono::hours;
        using std::chrono::minutes;
        using std::chrono::seconds;
        using std::chrono::milliseconds;
        using std::chrono::microseconds;
        using std::chrono::nanoseconds;
        using std::chrono::duration_cast;

        auto nanos = elapsedNanos();
        auto nanos_as_double = static_cast<double>(nanos.count());

        if (duration_cast<hours>(nanos) > hours())
        {
            auto t = nanos_as_double / duration_cast<nanoseconds>(hours(1)).count();
            return Strings::format("%.4g h", t);
        }

        if (duration_cast<minutes>(nanos) > minutes())
        {
            auto t = nanos_as_double / duration_cast<nanoseconds>(minutes(1)).count();
            return Strings::format("%.4g min", t);
        }

        if (duration_cast<seconds>(nanos) > seconds())
        {
            auto t = nanos_as_double / duration_cast<nanoseconds>(seconds(1)).count();
            return Strings::format("%.4g s", t);
        }

        if (duration_cast<milliseconds>(nanos) > milliseconds())
        {
            auto t = nanos_as_double / duration_cast<nanoseconds>(milliseconds(1)).count();
            return Strings::format("%.4g ms", t);
        }

        if (duration_cast<microseconds>(nanos) > microseconds())
        {
            auto t = nanos_as_double / duration_cast<nanoseconds>(microseconds(1)).count();
            return Strings::format("%.4g us", t);
        }

        return Strings::format("%.4g ns", nanos_as_double);
    }

    Stopwatch::Stopwatch() : m_isRunning(false), m_elapsedNanos(), m_startTick()
    {
    }

    std::chrono::nanoseconds Stopwatch::elapsedNanos() const
    {
        if (this->m_isRunning)
        {
            return std::chrono::high_resolution_clock::now() - this->m_startTick + this->m_elapsedNanos;
        }

        return this->m_elapsedNanos;
    }
}