File: SpringTime.h

package info (click to toggle)
spring 106.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,316 kB
  • sloc: cpp: 543,954; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (164 lines) | stat: -rw-r--r-- 6,549 bytes parent folder | download | duplicates (4)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef SPRINGTIME_H
#define SPRINGTIME_H

#include "System/creg/creg_cond.h"

#include <cinttypes>
#include <cassert>

#undef gt
#include <chrono>
namespace chrono { using namespace std::chrono; }






namespace spring_clock {
	// NOTE:
	//   1e-x are double-precision literals but T can be float
	//   floats only provide ~6 decimal digits of precision so
	//   ToSecs is inaccurate in that case
	//   these cannot be written as integer divisions or tests
	//   will fail because of intermediate conversions to FP32
	template<typename T> static T ToSecs     (const std::int64_t ns) { return (ns * 1e-9); }
	template<typename T> static T ToMilliSecs(const std::int64_t ns) { return (ns * 1e-6); }
	template<typename T> static T ToMicroSecs(const std::int64_t ns) { return (ns * 1e-3); }
	template<typename T> static T ToNanoSecs (const std::int64_t ns) { return (ns       ); }

	// specializations
	template<> std::int64_t ToSecs     <std::int64_t>(const std::int64_t ns) { return (ns / std::int64_t(1e9)); }
	template<> std::int64_t ToMilliSecs<std::int64_t>(const std::int64_t ns) { return (ns / std::int64_t(1e6)); }
	template<> std::int64_t ToMicroSecs<std::int64_t>(const std::int64_t ns) { return (ns / std::int64_t(1e3)); }

	template<typename T> static std::int64_t FromSecs     (const T  s) { return ( s * std::int64_t(1e9)); }
	template<typename T> static std::int64_t FromMilliSecs(const T ms) { return (ms * std::int64_t(1e6)); }
	template<typename T> static std::int64_t FromMicroSecs(const T us) { return (us * std::int64_t(1e3)); }
	template<typename T> static std::int64_t FromNanoSecs (const T ns) { return (ns                      ); }

	void PushTickRate(bool hres = false);
	void PopTickRate();

	// number of ticks since clock epoch
	std::int64_t GetTicks();
	const char* GetName();
}



// class Timer
struct spring_time {
private:
	CR_DECLARE_STRUCT(spring_time)

	typedef std::int64_t int64;

public:
	spring_time(): x(0) {}
	template<typename T> explicit spring_time(const T millis): x(spring_clock::FromMilliSecs(millis)) {}

	spring_time& operator+=(const spring_time st)       { x += st.x; return *this; }
	spring_time& operator-=(const spring_time st)       { x -= st.x; return *this; }
	spring_time& operator%=(const spring_time mt)       { x %= mt.x; return *this; }
	spring_time& operator*=(const int n)                { x *= n; return *this; }
	spring_time& operator*=(const float n)              { x *= n; return *this; }
	spring_time   operator-(const spring_time st) const { return spring_time_native(x - st.x); }
	spring_time   operator+(const spring_time st) const { return spring_time_native(x + st.x); }
	spring_time   operator%(const spring_time mt) const { return spring_time_native(x % mt.x); }
	bool          operator<(const spring_time st) const { return (x <  st.x); }
	bool          operator>(const spring_time st) const { return (x >  st.x); }
	bool         operator<=(const spring_time st) const { return (x <= st.x); }
	bool         operator>=(const spring_time st) const { return (x >= st.x); }

	spring_time   operator*(const int n)   const { return spring_time_native(x * n); }
	spring_time   operator*(const float n) const { return spring_time_native(x * n); }

	// short-hands
	int64 toSecsi()        const { return (toSecs     <int64>()); }
	int64 toMilliSecsi()   const { return (toMilliSecs<int64>()); }
	int64 toMicroSecsi()   const { return (toMicroSecs<int64>()); }
	int64 toNanoSecsi()    const { return (toNanoSecs <int64>()); }

	float toSecsf()      const { return (toSecs     <float>()); }
	float toMilliSecsf() const { return (toMilliSecs<float>()); }
	float toMicroSecsf() const { return (toMicroSecs<float>()); }
	float toNanoSecsf()  const { return (toNanoSecs <float>()); }

	// wrappers
	template<typename T> T toSecs()      const { return spring_clock::ToSecs     <T>(x); }
	template<typename T> T toMilliSecs() const { return spring_clock::ToMilliSecs<T>(x); }
	template<typename T> T toMicroSecs() const { return spring_clock::ToMicroSecs<T>(x); }
	template<typename T> T toNanoSecs()  const { return spring_clock::ToNanoSecs <T>(x); }


	bool isDuration() const { return (x != 0); }
	bool isTime() const { return (x > 0); }

	void sleep(bool forceThreadSleep = false);
	void sleep_until();


	static spring_time gettime(bool init = false) { assert(xs != 0 || init); return spring_time_native(spring_clock::GetTicks()); }
	static spring_time getstarttime() { assert(xs != 0); return spring_time_native(xs); }
	static spring_time getelapsedtime() { return (gettime() - getstarttime()); }

	static void setstarttime(const spring_time t) { assert(xs == 0); xs = t.x; assert(xs != 0); }

	static spring_time fromNanoSecs (const int64 ns) { return spring_time_native(spring_clock::FromNanoSecs( ns)); }
	static spring_time fromMicroSecs(const int64 us) { return spring_time_native(spring_clock::FromMicroSecs(us)); }
	static spring_time fromMilliSecs(const int64 ms) { return spring_time_native(spring_clock::FromMilliSecs(ms)); }
	static spring_time fromSecs     (const int64  s) { return spring_time_native(spring_clock::FromSecs     ( s)); }

private:
	// convert integer to spring_time (n is interpreted as number of nanoseconds)
	static spring_time spring_time_native(const int64 n) { spring_time s; s.x = n; return s; }
	void Serialize(creg::ISerializer* s);

private:
	int64 x;

	// initial time (the "Spring epoch", program start)
	// all other time-points *must* be larger than this
	// if the clock is monotonically increasing
	static int64 xs;
};



static const spring_time spring_notime(0);
static const spring_time spring_nulltime(0);

//#define spring_gettime()      spring_time::gettime()
#define spring_gettime()      spring_time::getelapsedtime()
#define spring_getstarttime() spring_time::getstarttime()
#define spring_now()          spring_time::getelapsedtime()

#define spring_tomsecs(t) ((t).toMilliSecsi())
#define spring_istime(t) ((t).isTime())
#define spring_sleep(t) ((t).sleep())

#define spring_msecs(msecs) spring_time(msecs)
#define spring_secs(secs) spring_time((secs) * 1000)





#define spring_difftime(now, before)  (now - before)
#define spring_diffsecs(now, before)  ((now - before).toSecsi())
#define spring_diffmsecs(now, before) ((now - before).toMilliSecsi())

#ifdef UNIT_TEST
struct InitSpringTime{
	InitSpringTime()
	{
		spring_clock::PushTickRate(true);
		spring_time::setstarttime(spring_time::gettime(true));
	}
};
#endif

#endif // SPRINGTIME_H