Make the standard time code work on a Teensy
This is a much nicer API to work with.
Change-Id: I5a654e8d953e5b64b76192d5b4ddb947b666d22f
diff --git a/aos/time/time.h b/aos/time/time.h
index 9bef741..6f69aa7 100644
--- a/aos/time/time.h
+++ b/aos/time/time.h
@@ -39,6 +39,8 @@
namespace time {
+#ifdef __linux__
+
// Enables returning the mock time value for Now instead of checking the system
// clock.
void EnableMockTime(monotonic_clock::time_point now);
@@ -78,6 +80,8 @@
DISALLOW_COPY_AND_ASSIGN(TimeFreezer);
};
+#endif // __linux__
+
// Converts a monotonic_clock::duration into a timespec object.
struct timespec to_timespec(::aos::monotonic_clock::duration duration);
@@ -85,9 +89,72 @@
// epoch.
struct timespec to_timespec(::aos::monotonic_clock::time_point time);
+namespace time_internal {
+
+template <class T>
+struct is_duration : std::false_type {};
+template <class Rep, class Period>
+struct is_duration<std::chrono::duration<Rep, Period>> : std::true_type {};
+
+} // namespace time_internal
+
+// Returns the greatest duration t representable in ToDuration that is less or
+// equal to d.
+// Implementation copied from
+// https://en.cppreference.com/w/cpp/chrono/duration/floor.
+// TODO(Brian): Remove once we have C++17 support.
+template <class To, class Rep, class Period,
+ class = std::enable_if_t<time_internal::is_duration<To>{}>>
+constexpr To floor(const std::chrono::duration<Rep, Period> &d) {
+ To t = std::chrono::duration_cast<To>(d);
+ if (t > d) return t - To{1};
+ return t;
+}
+
+// Returns the value t representable in ToDuration that is the closest to d. If
+// there are two such values, returns the even value (that is, the value t such
+// that t % 2 == 0).
+// Implementation copied from
+// https://en.cppreference.com/w/cpp/chrono/duration/round.
+// TODO(Brian): Remove once we have C++17 support.
+template <class To, class Rep, class Period,
+ class = std::enable_if_t<
+ time_internal::is_duration<To>{} &&
+ !std::chrono::treat_as_floating_point<typename To::rep>{}>>
+constexpr To round(const std::chrono::duration<Rep, Period> &d) {
+ To t0 = aos::time::floor<To>(d);
+ To t1 = t0 + To{1};
+ auto diff0 = d - t0;
+ auto diff1 = t1 - d;
+ if (diff0 == diff1) {
+ if (t0.count() & 1) return t1;
+ return t0;
+ } else if (diff0 < diff1) {
+ return t0;
+ }
+ return t1;
+}
+
+// Returns the nearest time point to tp representable in ToDuration, rounding to
+// even in halfway cases, like std::chrono::round in C++17.
+// Implementation copied from
+// https://en.cppreference.com/w/cpp/chrono/time_point/round.
+// TODO(Brian): Remove once we have C++17 support.
+template <class To, class Clock, class FromDuration,
+ class = std::enable_if_t<
+ time_internal::is_duration<To>{} &&
+ !std::chrono::treat_as_floating_point<typename To::rep>{}>>
+constexpr std::chrono::time_point<Clock, To> round(
+ const std::chrono::time_point<Clock, FromDuration> &tp) {
+ return std::chrono::time_point<Clock, To>{
+ aos::time::round<To>(tp.time_since_epoch())};
+}
+
} // namespace time
} // namespace aos
+#ifdef __linux__
+
namespace std {
namespace this_thread {
// Template specialization for monotonic_clock, since we can use clock_nanosleep
@@ -98,5 +165,6 @@
} // namespace this_thread
} // namespace std
+#endif // __linux__
#endif // AOS_TIME_H_