27 # include <inttypes.h>
30 # if defined(ZTH_OS_MAC) || defined(ZTH_OS_BAREMETAL)
31 # ifdef ZTH_CUSTOM_CLOCK_GETTIME
32 extern "C" int clock_gettime(
int clk_id,
struct timespec* res);
35 clock_nanosleep(
int clk_id,
int flags,
struct timespec
const* request,
struct timespec* remain);
36 # ifndef CLOCK_MONOTONIC
37 # define CLOCK_MONOTONIC 1
39 # ifndef TIMER_ABSTIME
40 # define TIMER_ABSTIME 1
76 # if __cplusplus >= 201103L
78 constexpr
TimeInterval(time_t
s,
long ns = 0,
bool negative =
false) noexcept
80 , m_negative{negative}
84 TimeInterval(time_t
s,
long ns = 0,
bool negative =
false) noexcept
86 , m_negative(negative)
103 m_negative = t.m_negative;
109 , m_negative(t.isNegative())
117 init_float<float>(dt);
125 init_float<double>(dt);
133 init_float<long double>(dt);
136 template <
typename T>
145 template <
typename T>
148 if(
s > std::numeric_limits<time_t>::max())
149 return TimeInterval(std::numeric_limits<time_t>::max(), 999999999L);
154 template <
typename T>
158 if((
unsigned long long)s_ > (
unsigned long long)std::numeric_limits<time_t>::max())
159 return TimeInterval(std::numeric_limits<time_t>::max(), 999999999L);
161 return TimeInterval((time_t)s_, ((
long)ms % 1000L) * 1000000L);
164 template <
typename T>
167 T s_ = us / (T)1000000;
168 if((
unsigned long long)s_ > (
unsigned long long)std::numeric_limits<time_t>::max())
169 return TimeInterval(std::numeric_limits<time_t>::max(), 999999999L);
171 return TimeInterval((time_t)s_, ((
long)us % 1000000L) * 1000L);
174 template <
typename T>
177 T s_ = ns / (T)1000000000L;
178 if(s_ > std::numeric_limits<time_t>::max())
179 return TimeInterval(std::numeric_limits<time_t>::max(), 999999999L);
181 return TimeInterval((time_t)s_, (
long)ns % 1000000000L);
185 template <
typename T>
186 void init_float(T dt)
192 if(std::fabs(dt) > (T)(std::numeric_limits<time_t>::max() / 2 - 1))
193 m_t.tv_sec = std::numeric_limits<time_t>::max();
195 m_t.tv_sec = (time_t)std::fabs(dt);
196 m_t.tv_nsec = (long)(std::fmod(std::fabs(dt), (T)1.0) * (T)1e9);
204 template <
typename T>
209 m_t.tv_sec = (time_t)(dt >= 0 ? dt : -dt);
216 return m_t.tv_sec >= 0 && m_t.tv_nsec >= 0 && m_t.tv_nsec <
BILLION;
231 return m_t.tv_sec == 0 && m_t.tv_nsec == 0;
236 return m_t.tv_sec > std::numeric_limits<time_t>::max() / 2;
244 constexpr
struct timespec const&
ts() const noexcept
254 template <
typename T>
257 T t = (T)m_t.tv_sec + (T)m_t.tv_nsec * (T)1e-9;
265 return m_t.tv_sec > t.m_t.tv_sec
266 || (m_t.tv_sec == t.m_t.tv_sec && m_t.tv_nsec > t.m_t.tv_nsec);
271 return (!m_negative && t.m_negative)
273 || (m_negative && t.m_negative && t.isAbsBiggerThan(*
this));
278 return m_t.tv_nsec == rhs.m_t.tv_nsec && m_t.tv_sec == rhs.m_t.tv_sec
279 && m_negative == rhs.m_negative;
294 return !(*
this >= rhs);
299 return *
this == rhs || !(*
this > rhs);
304 if(t.m_negative == m_negative) {
307 || std::numeric_limits<time_t>::max() - m_t.tv_sec - 1 <= t.m_t.tv_sec) {
308 m_t.tv_sec = std::numeric_limits<time_t>::max();
311 m_t.tv_sec += t.m_t.tv_sec;
312 m_t.tv_nsec += t.m_t.tv_nsec;
319 if(t.isAbsBiggerThan(*
this)) {
321 m_t.tv_sec = t.m_t.tv_sec - m_t.tv_sec;
322 m_t.tv_nsec = t.m_t.tv_nsec - m_t.tv_nsec;
323 m_negative = !m_negative;
326 m_t.tv_sec -= t.m_t.tv_sec;
327 m_t.tv_nsec -= t.m_t.tv_nsec;
329 if(m_t.tv_nsec < 0) {
341 template <
typename T>
378 template <
typename T>
385 template <
typename T>
391 template <
typename T>
398 template <
typename T>
415 # ifdef ZTH_OS_BAREMETAL
418 res +=
format(
"%u s", (
unsigned int)m_t.tv_sec);
419 else if(m_t.tv_sec > 0)
421 format(
"%u.%03u s", (
unsigned int)m_t.tv_sec,
422 (
unsigned int)(m_t.tv_nsec / 1000000L));
424 res +=
format(
"%u us", (
unsigned int)m_t.tv_nsec / 1000U);
426 uint64_t d = (uint64_t)(m_t.tv_sec / 3600 / 24);
427 time_t rest = m_t.tv_sec - d * 3600 * 24;
428 bool doPrint = d > 0;
430 res +=
format(
"%" PRIu64
"d:", d);
432 int h = int(rest / 3600);
435 res +=
format(
"%02d:", h);
441 int m = int(rest / 60);
444 res +=
format(
"%02d:", m);
450 double sec = (double)rest + (
double)m_t.tv_nsec * 1e-9;
452 res +=
format(
"%06.3f", sec);
454 res +=
format(
"%g s", sec);
472 # if __cplusplus >= 201103L
482 return TimeInterval((time_t)std::min<unsigned long long int>(
483 x, (
unsigned long long int)std::numeric_limits<time_t>::max()));
557 int res __attribute__((unused)) = clock_gettime(CLOCK_MONOTONIC, &t.m_t);
563 constexpr
struct timespec const&
ts() const noexcept
567 constexpr
operator struct timespec const &()
const noexcept
574 return ts().tv_sec < t.ts().tv_sec
575 || (
ts().tv_sec == t.ts().tv_sec &&
ts().tv_nsec < t.ts().tv_nsec);
580 return t.isBefore(*
this);
590 return ts().tv_nsec == rhs.ts().tv_nsec &&
ts().tv_sec == rhs.ts().tv_sec;
595 return !(*
this == rhs);
603 return *
this == rhs || this->
isBefore(rhs);
607 return rhs.isBefore(*
this);
611 return *
this == rhs || rhs.isBefore(*
this);
627 t.m_t.tv_sec -= m_t.tv_sec;
628 t.m_t.tv_nsec -= m_t.tv_nsec;
629 if(t.m_t.tv_nsec < 0) {
671 return rhs.timeTo(*
this);
681 return m_t.tv_sec == 0 && m_t.tv_nsec == 0;
Convenient wrapper around struct timespec that contains a time interval.
constexpr bool operator==(TimeInterval const &rhs) const noexcept
constexpr TimeInterval operator+(TimeInterval const &rhs) const noexcept
constexpr TimeInterval(T dt) noexcept
static constexpr TimeInterval from_s(T s)
constexpr bool operator>(TimeInterval const &rhs) const noexcept
constexpr TimeInterval operator-(TimeInterval const &rhs) const noexcept
static constexpr TimeInterval from_ms(T ms)
constexpr bool isInfinite() const noexcept
constexpr TimeInterval & operator*=(T x) noexcept
static constexpr TimeInterval from_ns(T ns)
constexpr TimeInterval & operator/=(T x) noexcept
constexpr void sub(TimeInterval const &t) noexcept
constexpr bool hasPassed() const noexcept
constexpr TimeInterval() noexcept
constexpr TimeInterval operator/(T x) const noexcept
constexpr void add(TimeInterval const &t) noexcept
constexpr void mul(T x) noexcept
static constexpr TimeInterval from_us(T us)
constexpr bool operator<=(TimeInterval const &rhs) const noexcept
constexpr bool isPositive() const noexcept
constexpr struct timespec const & ts() const noexcept
constexpr bool operator>=(TimeInterval const &rhs) const noexcept
TimeInterval & operator=(TimeInterval const &t) noexcept
constexpr static TimeInterval infinity() noexcept
constexpr TimeInterval & operator-=(TimeInterval const &rhs) noexcept
constexpr TimeInterval(time_t s, long ns=0, bool negative=false) noexcept
constexpr double s() const noexcept
constexpr T s() const noexcept
constexpr bool isNegative() const noexcept
TimeInterval(long double dt)
static long const BILLION
constexpr bool isNull() const noexcept
constexpr bool operator<(TimeInterval const &rhs) const noexcept
constexpr bool isAbsBiggerThan(TimeInterval const &t) const noexcept
constexpr TimeInterval operator-() const noexcept
constexpr TimeInterval(TimeInterval const &t) noexcept
constexpr TimeInterval operator*(T x) const noexcept
constexpr TimeInterval(struct timespec const &ts) noexcept
constexpr bool isNormal() const noexcept
constexpr TimeInterval & operator+=(TimeInterval const &rhs) noexcept
constexpr bool isBiggerThan(TimeInterval const &t) const noexcept
Convenient wrapper around struct timespec that contains an absolute timestamp.
constexpr Timestamp & operator-=(TimeInterval const &dt) noexcept
constexpr Timestamp(struct timespec const &ts) noexcept
constexpr TimeInterval operator-(Timestamp const &rhs) const noexcept
constexpr bool operator==(Timestamp const &rhs) const noexcept
constexpr Timestamp operator-(TimeInterval const &dt) const noexcept
constexpr bool isNull() const noexcept
constexpr struct timespec const & ts() const noexcept
Timestamp(TimeInterval const &ti)
constexpr bool operator>=(Timestamp const &rhs) const noexcept
constexpr bool isAfter(Timestamp const &t) const noexcept
constexpr bool operator!=(Timestamp const &rhs) const noexcept
constexpr bool operator<(Timestamp const &rhs) const noexcept
bool hasPassed() const noexcept
constexpr void add(TimeInterval const &dt) noexcept
constexpr bool operator>(Timestamp const &rhs) const noexcept
constexpr Timestamp(time_t sec, long nsec=0) noexcept
constexpr Timestamp() noexcept
constexpr bool isBefore(Timestamp const &t) const noexcept
constexpr Timestamp & operator+=(TimeInterval const &dt) noexcept
constexpr TimeInterval timeTo(Timestamp const &t) const
TimeInterval passed() const
constexpr bool operator<=(Timestamp const &rhs) const noexcept
constexpr Timestamp operator+(TimeInterval const &dt) const noexcept
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
cow_string str< TimeInterval const & >(TimeInterval const &value)
Timestamp const startTime
string format(char const *fmt,...)
Format like sprintf(), but save the result in an zth::string.
#define zth_assert(expr)
assert(), but better integrated in Zth.