11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
22PROMEKI_NAMESPACE_BEGIN
50 PROMEKI_DATATYPE(TimeStamp, DataTypeTimeStamp, 1)
59 static constexpr int64_t Invalid = INT64_MIN;
62 Error writeToStream(DataStream &s) const;
64 template <uint32_t V> static Result<TimeStamp> readFromStream(DataStream &s);
67 using Clock = std::chrono::steady_clock;
69 using Value = std::chrono::time_point<Clock>;
71 using Duration = Clock::duration;
78 static Duration secondsToDuration(
double val) {
79 std::chrono::duration<double> doubleDuration(val);
80 return std::chrono::duration_cast<Duration>(doubleDuration);
87 static void sleep(
const Duration &d) {
88 std::this_thread::sleep_for(d);
96 static TimeStamp now() {
98 std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now().time_since_epoch())
103 TimeStamp() =
default;
114 explicit TimeStamp(int64_t ns) : _ns(ns) {}
120 TimeStamp(
const Value &v)
121 : _ns(std::chrono::duration_cast<std::chrono::nanoseconds>(v.time_since_epoch()).count()) {}
124 bool isValid()
const {
return _ns != Invalid; }
135 operator Value()
const {
return Value(std::chrono::nanoseconds(_ns)); }
146 TimeStamp &operator+=(
const Duration &duration) {
148 _ns += std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
162 TimeStamp &operator-=(
const Duration &duration) {
164 _ns -= std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
173 void setValue(
const Value &v) {
174 _ns = std::chrono::duration_cast<std::chrono::nanoseconds>(v.time_since_epoch()).count();
188 Value value()
const {
return Value(std::chrono::nanoseconds(_ns)); }
197 void invalidate() { _ns = Invalid; }
201 _ns = std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now().time_since_epoch())
210 void sleepUntil()
const {
211 if (isValid()) std::this_thread::sleep_until(value());
218 Duration timeSinceEpoch()
const {
219 return std::chrono::duration_cast<Duration>(std::chrono::nanoseconds(_ns));
229 double seconds()
const {
230 if (!isValid())
return 0.0;
231 return static_cast<double>(_ns) / 1'000'000'000.0;
241 int64_t milliseconds()
const {
242 if (!isValid())
return 0;
243 return _ns / 1'000'000LL;
253 int64_t microseconds()
const {
254 if (!isValid())
return 0;
255 return _ns / 1'000LL;
267 int64_t nanoseconds()
const {
return _ns; }
276 double elapsedSeconds()
const {
277 if (!isValid())
return 0.0;
278 return std::chrono::duration_cast<std::chrono::duration<double>>(Clock::now() - value()).count();
288 int64_t elapsedMilliseconds()
const {
289 if (!isValid())
return 0;
290 return std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - value()).count();
300 int64_t elapsedMicroseconds()
const {
301 if (!isValid())
return 0;
302 return std::chrono::duration_cast<std::chrono::microseconds>(Clock::now() - value()).count();
312 int64_t elapsedNanoseconds()
const {
313 if (!isValid())
return 0;
314 return std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now() - value()).count();
324 String toString()
const {
325 if (!isValid())
return String(
"invalid");
326 return String::number(seconds());
337 static Result<TimeStamp> fromString(
const String &s) {
338 if (s ==
"invalid")
return makeResult(TimeStamp());
340 double v = s.to<
double>(&e);
341 if (e.isError())
return makeError<TimeStamp>(Error::ParseFailed);
342 return makeResult(TimeStamp(Value(secondsToDuration(v))));
346 bool operator==(
const TimeStamp &other)
const {
return _ns == other._ns; }
349 bool operator!=(
const TimeStamp &other)
const {
return _ns != other._ns; }
352 bool operator<(
const TimeStamp &other)
const {
return _ns < other._ns; }
354 bool operator>(
const TimeStamp &other)
const {
return _ns > other._ns; }
356 bool operator<=(
const TimeStamp &other)
const {
return _ns <= other._ns; }
358 bool operator>=(
const TimeStamp &other)
const {
return _ns >= other._ns; }
361 operator String()
const {
return toString(); }
364 int64_t _ns = Invalid;
376inline TimeStamp operator+(
const TimeStamp &ts,
const TimeStamp::Duration &duration) {
377 TimeStamp result(ts);
391inline TimeStamp operator-(
const TimeStamp &ts,
const TimeStamp::Duration &duration) {
392 TimeStamp result(ts);
422inline TimeStamp::Duration toClockDuration(
const Duration &d) {
423 return std::chrono::duration_cast<TimeStamp::Duration>(std::chrono::nanoseconds(d.nanoseconds()));
435inline TimeStamp &operator+=(TimeStamp &ts,
const Duration &d) {
436 if (!ts.isValid() || !d.isValid()) {
439 ts = TimeStamp(ts.nanoseconds() + d.nanoseconds());
453inline TimeStamp &operator-=(TimeStamp &ts,
const Duration &d) {
454 if (!ts.isValid() || !d.isValid()) {
457 ts = TimeStamp(ts.nanoseconds() - d.nanoseconds());
471inline TimeStamp operator+(
const TimeStamp &ts,
const Duration &d) {
472 TimeStamp result(ts);
486inline TimeStamp operator-(
const TimeStamp &ts,
const Duration &d) {
487 TimeStamp result(ts);
506inline Duration operator-(
const TimeStamp &a,
const TimeStamp &b) {
507 if (!a.isValid() || !b.isValid())
return Duration();
508 return Duration::fromNanoseconds(a.nanoseconds() - b.nanoseconds());
513PROMEKI_FORMAT_VIA_TOSTRING(promeki::TimeStamp);