1 /* Copyright 2012-present Facebook, Inc.
2 * Licensed under the Apache License, Version 2.0 */
3 #pragma once
4 #include "watchman_system.h"
5 #include <chrono>
6
7 /* Return a timespec holding the equivalent of the supplied duration */
8 template <class Rep, class Period>
9 inline timespec
durationToTimeSpecDuration(const std::chrono::duration<Rep,Period> & d)10 durationToTimeSpecDuration(const std::chrono::duration<Rep, Period> &d) {
11 timespec ts{0,0};
12
13 ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
14 ts.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(
15 d - std::chrono::seconds(ts.tv_sec))
16 .count();
17 return ts;
18 }
19
20 /* Return a timespec holding an absolute time equivalent to the provided
21 * system_clock timepoint */
22 inline timespec
systemClockToTimeSpec(const std::chrono::system_clock::time_point & p)23 systemClockToTimeSpec(const std::chrono::system_clock::time_point &p) {
24 /* It just so happens that the epoch for system_clock is the same as the
25 * epoch for timespec, so we can use our duration helper on the duration
26 * since the epoch. */
27 return durationToTimeSpecDuration(p.time_since_epoch());
28 }
29
30 void w_timeoutms_to_abs_timespec(int timeoutms, struct timespec *deadline);
31
32 /* compare two timevals and return -1 if a is < b, 0 if a == b,
33 * or 1 if b > a */
w_timeval_compare(struct timeval a,struct timeval b)34 static inline int w_timeval_compare(struct timeval a, struct timeval b)
35 {
36 if (a.tv_sec < b.tv_sec) {
37 return -1;
38 }
39 if (a.tv_sec > b.tv_sec) {
40 return 1;
41 }
42 if (a.tv_usec < b.tv_usec) {
43 return -1;
44 }
45 if (a.tv_usec > b.tv_usec) {
46 return 1;
47 }
48 return 0;
49 }
50
51 #define WATCHMAN_USEC_IN_SEC 1000000
52 #define WATCHMAN_NSEC_IN_USEC 1000
53 #define WATCHMAN_NSEC_IN_SEC (1000 * 1000 * 1000)
54 #define WATCHMAN_NSEC_IN_MSEC 1000000
55
56 #if defined(__APPLE__) || defined(__FreeBSD__) \
57 || (defined(__NetBSD__) && (__NetBSD_Version__ < 6099000000))
58 /* BSD-style subsecond timespec */
59 #define WATCHMAN_ST_TIMESPEC(type) st_##type##timespec
60 #else
61 /* POSIX standard timespec */
62 #define WATCHMAN_ST_TIMESPEC(type) st_##type##tim
63 #endif
64
w_timeval_add(const struct timeval a,const struct timeval b,struct timeval * result)65 static inline void w_timeval_add(const struct timeval a,
66 const struct timeval b, struct timeval *result)
67 {
68 result->tv_sec = a.tv_sec + b.tv_sec;
69 result->tv_usec = a.tv_usec + b.tv_usec;
70
71 if (result->tv_usec > WATCHMAN_USEC_IN_SEC) {
72 result->tv_sec++;
73 result->tv_usec -= WATCHMAN_USEC_IN_SEC;
74 }
75 }
76
w_timeval_sub(const struct timeval a,const struct timeval b,struct timeval * result)77 static inline void w_timeval_sub(const struct timeval a,
78 const struct timeval b, struct timeval *result)
79 {
80 result->tv_sec = a.tv_sec - b.tv_sec;
81 result->tv_usec = a.tv_usec - b.tv_usec;
82
83 if (result->tv_usec < 0) {
84 result->tv_sec--;
85 result->tv_usec += WATCHMAN_USEC_IN_SEC;
86 }
87 }
88
w_timeval_to_timespec(const struct timeval a,struct timespec * ts)89 static inline void w_timeval_to_timespec(
90 const struct timeval a, struct timespec *ts)
91 {
92 ts->tv_sec = a.tv_sec;
93 ts->tv_nsec = a.tv_usec * WATCHMAN_NSEC_IN_USEC;
94 }
95
w_timespec_to_timeval(const struct timespec ts,struct timeval * tv)96 static inline void w_timespec_to_timeval(
97 const struct timespec ts, struct timeval *tv) {
98 tv->tv_sec = ts.tv_sec;
99 tv->tv_usec = ts.tv_nsec / WATCHMAN_NSEC_IN_USEC;
100 }
101
102 // Convert a timeval to a double that holds the fractional number of seconds
w_timeval_abs_seconds(struct timeval tv)103 static inline double w_timeval_abs_seconds(struct timeval tv){
104 double val = (double)tv.tv_sec;
105 val += ((double)tv.tv_usec)/WATCHMAN_USEC_IN_SEC;
106 return val;
107 }
108
w_timeval_diff(struct timeval start,struct timeval end)109 static inline double w_timeval_diff(struct timeval start, struct timeval end)
110 {
111 double s = start.tv_sec + ((double)start.tv_usec)/WATCHMAN_USEC_IN_SEC;
112 double e = end.tv_sec + ((double)end.tv_usec)/WATCHMAN_USEC_IN_SEC;
113
114 return e - s;
115 }
116