summaryrefslogtreecommitdiff
path: root/hrtime.h
diff options
context:
space:
mode:
Diffstat (limited to 'hrtime.h')
-rw-r--r--hrtime.h59
1 files changed, 59 insertions, 0 deletions
diff --git a/hrtime.h b/hrtime.h
index f133bdb1ac..7ed4e6b04c 100644
--- a/hrtime.h
+++ b/hrtime.h
@@ -36,6 +36,7 @@
#define RB_HRTIME_PER_MSEC (RB_HRTIME_PER_USEC * (rb_hrtime_t)1000)
#define RB_HRTIME_PER_SEC (RB_HRTIME_PER_MSEC * (rb_hrtime_t)1000)
#define RB_HRTIME_MAX UINT64_MAX
+#define RB_HRTIME_MIN ((rb_hrtime_t)0)
/*
* Lets try to support time travelers. Lets assume anybody with a time machine
@@ -91,6 +92,15 @@ rb_hrtime_add(rb_hrtime_t a, rb_hrtime_t b)
return c;
}
+static inline rb_hrtime_t
+rb_hrtime_sub(rb_hrtime_t a, rb_hrtime_t b)
+{
+ if (a < b) {
+ return RB_HRTIME_MIN;
+ }
+ return a - b;
+}
+
/*
* convert a timeval struct to rb_hrtime_t, clamping at RB_HRTIME_MAX
*/
@@ -165,4 +175,53 @@ rb_hrtime2timeval(struct timeval *tv, const rb_hrtime_t *hrt)
}
return 0;
}
+
+#include "internal/warnings.h"
+#include "internal/time.h"
+
+/*
+ * Back when we used "struct timeval", not all platforms implemented
+ * tv_sec as time_t. Nowadays we use "struct timespec" and tv_sec
+ * seems to be implemented more consistently across platforms.
+ * At least other parts of our code hasn't had to deal with non-time_t
+ * tv_sec in timespec...
+ */
+#define TIMESPEC_SEC_MAX TIMET_MAX
+#define TIMESPEC_SEC_MIN TIMET_MIN
+
+COMPILER_WARNING_PUSH
+#if __has_warning("-Wimplicit-int-float-conversion")
+COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion)
+#elif defined(_MSC_VER)
+/* C4305: 'initializing': truncation from '__int64' to 'const double' */
+COMPILER_WARNING_IGNORED(4305)
+#endif
+static const double TIMESPEC_SEC_MAX_as_double = TIMESPEC_SEC_MAX;
+COMPILER_WARNING_POP
+
+static inline rb_hrtime_t *
+double2hrtime(rb_hrtime_t *hrt, double d)
+{
+ /* assume timespec.tv_sec has same signedness as time_t */
+ const double TIMESPEC_SEC_MAX_PLUS_ONE = 2.0 * (TIMESPEC_SEC_MAX_as_double / 2.0 + 1.0);
+
+ if (TIMESPEC_SEC_MAX_PLUS_ONE <= d) {
+ *hrt = RB_HRTIME_MAX;
+ return NULL;
+ }
+ else if (d <= 0) {
+ *hrt = 0;
+ }
+ else {
+ *hrt = (rb_hrtime_t)(d * (double)RB_HRTIME_PER_SEC);
+ }
+ return hrt;
+}
+
+static inline double
+hrtime2double(rb_hrtime_t hrt)
+{
+ return (double)hrt / (double)RB_HRTIME_PER_SEC;
+}
+
#endif /* RB_HRTIME_H */