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