MythTV  master
mythchrono.h
Go to the documentation of this file.
1 #ifndef __MYTHCHRONO_H__
2 #define __MYTHCHRONO_H__
3 
4 #include <cmath>
5 #include <sys/time.h> // For gettimeofday
6 #include <QMetaType>
7 
8 
9 // Include the std::chrono definitions, and set up to parse the
10 // std::chrono literal suffixes.
11 #include <chrono>
12 using std::chrono::duration_cast;
13 using namespace std::chrono_literals;
14 Q_DECLARE_METATYPE(std::chrono::seconds);
15 Q_DECLARE_METATYPE(std::chrono::milliseconds);
16 Q_DECLARE_METATYPE(std::chrono::microseconds);
17 
18 // Grab the underlying std::chrono::duration data type for future use.
19 using CHRONO_TYPE = std::chrono::seconds::rep;
20 
21 // Copy these c++20 literals from the chrono header file
22 #if __cplusplus <= 201703L
23 namespace std::chrono // NOLINT(cert-dcl58-cpp)
24 {
25  using days = duration<CHRONO_TYPE, ratio<86400>>;
26  using weeks = duration<CHRONO_TYPE, ratio<604800>>;
27  using months = duration<CHRONO_TYPE, ratio<2629746>>;
28  using years = duration<CHRONO_TYPE, ratio<31556952>>;
29 }
30 #endif // C++20
31 
32 
33 //
34 // Set up some additional data types for use by MythTV.
35 //
36 
37 // There are a number of places that hold/manipulate time in the form
38 // of a floating point number. Create unique types for these.
39 using floatsecs = std::chrono::duration<double>;
40 using floatmsecs = std::chrono::duration<double, std::milli>;
41 using floatusecs = std::chrono::duration<double, std::micro>;
42 
43 // There are a handful of places that hold a time value in units of
44 // AV_TIME_BASE. Create a unique type for this.
45 #if defined AV_TIME_BASE
46 using av_duration = std::chrono::duration<int64_t,std::ratio<1,AV_TIME_BASE>>;
47 #endif
48 
49 // Define namespaces for the presentation timestamp and a literal
50 // suffix, and set up to parse the literal suffix.
51 namespace mpeg
52 {
53  namespace chrono
54  {
55  using pts = std::chrono::duration<CHRONO_TYPE, std::ratio<1, 90000>>;
56  }
57  namespace chrono_literals
58  {
59  constexpr mpeg::chrono::pts operator ""_pts(unsigned long long v) {
60  return mpeg::chrono::pts(v); }
61  }
62 }
63 using namespace mpeg::chrono_literals;
64 
65 // Set up types to easily reference the system clock.
66 using SystemClock = std::chrono::system_clock;
67 using SystemTime = std::chrono::time_point<SystemClock>;
68 
69 
70 //
71 // Functions for converting existing data types to std::chrono.
72 //
73 
75 //
76 // \param value A floating point number that represents a time in seconds.
77 // \returns The same number of seconds as a std::chrono::seconds.
78 template <typename T>
79 typename std::enable_if_t<std::is_floating_point_v<T>, std::chrono::seconds>
81 {
82  return std::chrono::seconds(static_cast<int64_t>(value));
83 }
84 
86 //
87 // \param value A floating point number that represents a time in milliseconds.
88 // \returns The same number of seconds as a std::chrono::milliseconds.
89 template <typename T>
90 typename std::enable_if_t<std::is_floating_point_v<T>, std::chrono::milliseconds>
92 {
93  return std::chrono::milliseconds(static_cast<int64_t>(value));
94 }
95 
97 //
98 // \param value A floating point number that represents a time in microseconds.
99 // \returns The same number of seconds as a std::chrono::microseconds.
100 template <typename T>
101 typename std::enable_if_t<std::is_floating_point_v<T>, std::chrono::microseconds>
103 {
104  return std::chrono::microseconds(static_cast<int64_t>(value));
105 }
106 
108 static constexpr
109 std::chrono::milliseconds millisecondsFromParts (int hours, int minutes = 0,
110  int seconds = 0, int milliseconds = 0)
111 {
112  return std::chrono::hours(hours)
113  + std::chrono::minutes(minutes)
114  + std::chrono::seconds(seconds)
115  + std::chrono::milliseconds(milliseconds);
116 }
117 
119 //
120 // Always specify the desired precision when calling this function.
121 // I.E. Always call in the form:
122 // durationFromTimeval<std::chrono::milliseconds>(t);
123 //
124 // Timevals can support a precision as small as microseconds.
125 template <typename T>
126 constexpr T durationFromTimeval (timeval t)
127 {
128  std::chrono::microseconds value = std::chrono::seconds(t.tv_sec) +
129  std::chrono::microseconds(t.tv_usec);
130  if constexpr (std::is_same_v<T,std::chrono::microseconds>)
131  return value;
132  return duration_cast<T>(value);
133 }
134 
136 //
137 // Always specify the desired precision when calling this function.
138 // I.E. Always call in the form:
139 // durationFromTimevalDelta<std::chrono::milliseconds>(t);
140 //
141 // Timevals can support a precision as small as microseconds.
142 template <typename T>
143 constexpr T durationFromTimevalDelta (timeval a, timeval b)
144 {
145  auto usec_a = durationFromTimeval<std::chrono::microseconds>(a);
146  auto usec_b = durationFromTimeval<std::chrono::microseconds>(b);
147  if constexpr (std::is_same_v<T,std::chrono::microseconds>)
148  return usec_a - usec_b;
149  return duration_cast<T>(usec_a - usec_b);
150 }
151 
153 //
154 // Always specify the desired precision when calling this function.
155 // I.E. Always call in the form:
156 // durationFromTimespec<std::chrono::milliseconds>(t);
157 //
158 // Timevals can support a precision as small as nanoseconds.
159 template <typename T>
160 constexpr T durationFromTimespec (struct timespec time)
161 {
162  std::chrono::nanoseconds nsec = std::chrono::seconds(time.tv_sec)
163  + std::chrono::nanoseconds(time.tv_nsec);
164  if constexpr (std::is_same_v<T,std::chrono::nanoseconds>)
165  return nsec;
166  return duration_cast<T>(nsec);
167 }
168 
169 
170 //
171 // Get current time as std::chrono duration
172 //
173 
175 //
176 // Always specify the desired precision when calling this function.
177 // I.E. Always call in the form:
178 // nowAsDuration<std::chrono::milliseconds>(t);
179 //
180 // This function is based upon the gettimeoday function, so can
181 // return precisions as small as microseconds.
182 template <typename T>
183 T nowAsDuration (bool adjustForTZ = false)
184 {
185  struct timeval now {};
186  struct timezone tz {};
187  gettimeofday(&now, &tz);
188 
189  auto usecs = durationFromTimeval<std::chrono::microseconds>(now);
190  if (adjustForTZ)
191  usecs -= std::chrono::minutes(tz.tz_minuteswest);
192  if constexpr (std::is_same_v<T,std::chrono::microseconds>)
193  return usecs;
194  return duration_cast<T>(usecs);
195 }
196 
198 template <typename T>
199 static constexpr T chronomult(T duration, double f)
200 {
201  return T(std::llround(duration.count() * f));
202 }
204 template <typename T>
205 static constexpr T chronodivide(T duration, double f)
206 {
207  return T(std::llround(duration.count() / f));
208 }
209 
210 #endif // __MYTHCHRONO_H__
nowAsDuration
T nowAsDuration(bool adjustForTZ=false)
Get the currenttime as a duration.
Definition: mythchrono.h:183
secondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::seconds > secondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:80
mpeg
Definition: mythchrono.h:51
durationFromTimevalDelta
constexpr T durationFromTimevalDelta(timeval a, timeval b)
Compute delta between timevals and convert to a duration.
Definition: mythchrono.h:143
SystemTime
std::chrono::time_point< SystemClock > SystemTime
Definition: mythchrono.h:67
chronomult
static constexpr T chronomult(T duration, double f)
Multiply a duration by a float, returning a duration.
Definition: mythchrono.h:199
microsecondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::microseconds > microsecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:102
millisecondsFromParts
static constexpr std::chrono::milliseconds millisecondsFromParts(int hours, int minutes=0, int seconds=0, int milliseconds=0)
Build a duration from separate minutes, seconds, etc.
Definition: mythchrono.h:109
std::chrono::years
duration< CHRONO_TYPE, ratio< 31556952 > > years
Definition: mythchrono.h:28
floatsecs
std::chrono::duration< double > floatsecs
Definition: mythchrono.h:39
Q_DECLARE_METATYPE
Q_DECLARE_METATYPE(std::chrono::seconds)
hardwareprofile.i18n.t
t
Definition: i18n.py:36
CHRONO_TYPE
std::chrono::seconds::rep CHRONO_TYPE
Definition: mythchrono.h:19
mpeg::chrono_literals
Definition: mythchrono.h:57
floatusecs
std::chrono::duration< double, std::micro > floatusecs
Definition: mythchrono.h:41
durationFromTimeval
constexpr T durationFromTimeval(timeval t)
Convert a timeval to a duration.
Definition: mythchrono.h:126
SystemClock
std::chrono::system_clock SystemClock
Definition: mythchrono.h:66
durationFromTimespec
constexpr T durationFromTimespec(struct timespec time)
Convert a timespec to a duration.
Definition: mythchrono.h:160
chronodivide
static constexpr T chronodivide(T duration, double f)
Divide a duration by a float, returning a duration.
Definition: mythchrono.h:205
std::chrono::days
duration< CHRONO_TYPE, ratio< 86400 > > days
Definition: mythchrono.h:25
mpeg::chrono::pts
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:55
std::chrono::months
duration< CHRONO_TYPE, ratio< 2629746 > > months
Definition: mythchrono.h:27
std::chrono::weeks
duration< CHRONO_TYPE, ratio< 604800 > > weeks
Definition: mythchrono.h:26
floatmsecs
std::chrono::duration< double, std::milli > floatmsecs
Definition: mythchrono.h:40
millisecondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::milliseconds > millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:91
std::chrono
Definition: mythchrono.h:23