1 | // tTimer.h  |
2 | //  |
3 | // Simple timer class. Like a stopwatch. Supports keeping track of time in a number of different units. Accuracy is all  |
4 | // up to you - you call the update function. This code does not access low-level timer hardware.  |
5 | //  |
6 | // Copyright (c) 2005, 2017, 2019, 2020 Tristan Grimmer.  |
7 | // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby  |
8 | // granted, provided that the above copyright notice and this permission notice appear in all copies.  |
9 | //  |
10 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL  |
11 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,  |
12 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN  |
13 | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR  |
14 | // PERFORMANCE OF THIS SOFTWARE.  |
15 |   |
16 | #pragma once  |
17 | #include <ctime>  |
18 | #include <Foundation/tPlatform.h>  |
19 | #include <Foundation/tAssert.h>  |
20 | #include <Foundation/tUnits.h>  |
21 | namespace tSystem  |
22 | {  |
23 |   |
24 |   |
25 | // High accuracy cross platform timing functions. For windows the frequency is whatever the HW reports. For other  |
26 | // platforms it's 1/1ns = 1000000000Hz but counts increment by whatever the internal timer resulution is in ns.  |
27 | int64 tGetHardwareTimerFrequency();  |
28 | int64 tGetHardwareTimerCount();  |
29 |   |
30 |   |
31 | // Gets the number of seconds since the absolute time reference of 00:00:00 Coordinated Universal Time (UTC),  |
32 | // Thursday, 1 January 1970. The std::time_t is essentially a big integer.  |
33 | std::time_t tGetTimeUTC();  |
34 | std::time_t tGetTimeGMT();  |
35 |   |
36 |   |
37 | // Gets the current local time. Takes into account your timezone, DST, etc.  |
38 | // std::tm is a field-based time format, HH, MM, SS etc.  |
39 | std::tm tGetTimeLocal();  |
40 | std::tm tConvertTimeToLocal(std::time_t);  |
41 |   |
42 |   |
43 | // Return a timepoint as a string.  |
44 | enum class tTimeFormat  |
45 | {  |
46 | Standard, // Eg. 2020-01-14 01:47:12  |
47 | Extended, // Eg. Tuesday January 14 2020 - 01:36:34  |
48 | Short, // Eg. Tue Jan 14 14:38:58 2020  |
49 | };  |
50 | tString tConvertTimeToString(std::tm, tTimeFormat = tTimeFormat::Standard);  |
51 |   |
52 |   |
53 | // Gets the number of seconds since application start. Uses the high-performance counter,  |
54 | float tGetTime();  |
55 | double tGetTimeDouble();  |
56 | void tSleep(int milliSeconds);  |
57 |   |
58 |   |
59 | class tTimer  |
60 | {  |
61 | public:  |
62 | // Creates a timer. You can specify whether the timer is constructed started or not. Internally a floating-point  |
63 | // (double) member is used to keep track of the elapsed time. You can choose the units it represents, which has  |
64 | // implications for overall timer precision. In general, use an internal unit that matches your domain - timing  |
65 | // oscillations of visible light? Use nanoseconds. If unit is Unspecified seconds are used.  |
66 | tTimer(bool start = true, tUnit::tTime unit = tUnit::tTime::Second) : UnitInternal(unit), Running(start), Time(0.0f) { if (UnitInternal == tUnit::tTime::Unspecified) UnitInternal = tUnit::tTime::Second; }  |
67 |   |
68 | // Call this frequently. If Unit is not specified, internal units are used.  |
69 | void Update(float timeElapsed, tUnit::tTime = tUnit::tTime::Unspecified);  |
70 |   |
71 | // Does nothing (idempotent) if timer already started (or stopped).  |
72 | void Start() { Running = true; }  |
73 | void Stop() { Running = false; }  |
74 | void Reset(bool start = true) { Time = 0.0; Running = start; }  |
75 |   |
76 | // Returns the time in the units of Unit. If Unit is not specified, uses internal units.  |
77 | float GetTime(tUnit::tTime = tUnit::tTime::Unspecified) const;  |
78 | bool IsRunning() const { return Running; }  |
79 | tUnit::tTime GetInternalUnit() const { return UnitInternal; }  |
80 |   |
81 | static double Convert(double time, tUnit::tTime from, tUnit::tTime to);  |
82 |   |
83 | private:  |
84 | // @todo Add getters that format the time into a number of different string formats.  |
85 | const static double UnitConversionTable[int(tUnit::tTime::NumTimeUnits)][int(tUnit::tTime::NumTimeUnits)];  |
86 |   |
87 | tUnit::tTime UnitInternal;  |
88 | bool Running;  |
89 | double Time;  |
90 |   |
91 | public:  |
92 | // For developers only. Easily add a new unit and recreate the unit conversion table.  |
93 | static void PrintHighPrecisionConversionTable(const char* outputFile);  |
94 | };  |
95 |   |
96 |   |
97 | }  |
98 | |