File Coverage

amqp_time.c
Criterion Covered Total %
statement 67 87 77.0
branch 33 52 63.4
condition n/a
subroutine n/a
pod n/a
total 100 139 71.9


line stmt bran cond sub pod time code
1             /*
2             * Portions created by Alan Antonuk are Copyright (c) 2013-2014 Alan Antonuk.
3             * All Rights Reserved.
4             *
5             * Permission is hereby granted, free of charge, to any person obtaining a
6             * copy of this software and associated documentation files (the "Software"),
7             * to deal in the Software without restriction, including without limitation
8             * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9             * and/or sell copies of the Software, and to permit persons to whom the
10             * Software is furnished to do so, subject to the following conditions:
11             *
12             * The above copyright notice and this permission notice shall be included in
13             * all copies or substantial portions of the Software.
14             *
15             * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16             * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17             * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18             * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19             * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20             * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21             * DEALINGS IN THE SOFTWARE.
22             */
23             #include "amqp_time.h"
24             #include "amqp.h"
25             #include
26             #include
27             #include
28              
29             #if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || \
30             defined(__MINGW32__) || defined(__MINGW64__))
31             #define AMQP_WIN_TIMER_API
32             #elif (defined(machintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
33             #define AMQP_MAC_TIMER_API
34             #else
35             #define AMQP_POSIX_TIMER_API
36             #endif
37              
38             #ifdef AMQP_WIN_TIMER_API
39             #ifndef WIN32_LEAN_AND_MEAN
40             #define WIN32_LEAN_AND_MEAN
41             #endif
42             #include
43              
44             uint64_t amqp_get_monotonic_timestamp(void) {
45             static double NS_PER_COUNT = 0;
46             LARGE_INTEGER perf_count;
47              
48             if (0 == NS_PER_COUNT) {
49             LARGE_INTEGER perf_frequency;
50             if (!QueryPerformanceFrequency(&perf_frequency)) {
51             return 0;
52             }
53             NS_PER_COUNT = (double)AMQP_NS_PER_S / perf_frequency.QuadPart;
54             }
55              
56             if (!QueryPerformanceCounter(&perf_count)) {
57             return 0;
58             }
59              
60             return (uint64_t)(perf_count.QuadPart * NS_PER_COUNT);
61             }
62             #endif /* AMQP_WIN_TIMER_API */
63              
64             #ifdef AMQP_MAC_TIMER_API
65             #include
66              
67             uint64_t amqp_get_monotonic_timestamp(void) {
68             static mach_timebase_info_data_t s_timebase = {0, 0};
69             uint64_t timestamp;
70              
71             timestamp = mach_absolute_time();
72              
73             if (s_timebase.denom == 0) {
74             mach_timebase_info(&s_timebase);
75             if (0 == s_timebase.denom) {
76             return 0;
77             }
78             }
79              
80             timestamp *= (uint64_t)s_timebase.numer;
81             timestamp /= (uint64_t)s_timebase.denom;
82              
83             return timestamp;
84             }
85             #endif /* AMQP_MAC_TIMER_API */
86              
87             #ifdef AMQP_POSIX_TIMER_API
88             #include
89              
90 376           uint64_t amqp_get_monotonic_timestamp(void) {
91             #ifdef __hpux
92             return (uint64_t)gethrtime();
93             #else
94             struct timespec tp;
95 376 50         if (-1 == clock_gettime(CLOCK_MONOTONIC, &tp)) {
96 0           return 0;
97             }
98              
99 376           return ((uint64_t)tp.tv_sec * AMQP_NS_PER_S + (uint64_t)tp.tv_nsec);
100             #endif
101             }
102             #endif /* AMQP_POSIX_TIMER_API */
103              
104 465           int amqp_time_from_now(amqp_time_t *time, const struct timeval *timeout) {
105             uint64_t now_ns;
106             uint64_t delta_ns;
107              
108 465 50         assert(NULL != time);
109              
110 465 100         if (NULL == timeout) {
111 341           *time = amqp_time_infinite();
112 341           return AMQP_STATUS_OK;
113             }
114              
115 124 50         if (timeout->tv_sec < 0 || timeout->tv_usec < 0) {
    50          
116 0           return AMQP_STATUS_INVALID_PARAMETER;
117             }
118              
119 248           delta_ns = (uint64_t)timeout->tv_sec * AMQP_NS_PER_S +
120 124           (uint64_t)timeout->tv_usec * AMQP_NS_PER_US;
121              
122 124           now_ns = amqp_get_monotonic_timestamp();
123 124 50         if (0 == now_ns) {
124 0           return AMQP_STATUS_TIMER_FAILURE;
125             }
126              
127 124           time->time_point_ns = now_ns + delta_ns;
128 124 50         if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
    50          
129 0           return AMQP_STATUS_INVALID_PARAMETER;
130             }
131              
132 124           return AMQP_STATUS_OK;
133             }
134              
135 1017           int amqp_time_s_from_now(amqp_time_t *time, int seconds) {
136             uint64_t now_ns;
137             uint64_t delta_ns;
138 1017 50         assert(NULL != time);
139              
140 1017 100         if (0 >= seconds) {
141 982           *time = amqp_time_infinite();
142 982           return AMQP_STATUS_OK;
143             }
144              
145 35           now_ns = amqp_get_monotonic_timestamp();
146 35 50         if (0 == now_ns) {
147 0           return AMQP_STATUS_TIMER_FAILURE;
148             }
149              
150 35           delta_ns = (uint64_t)seconds * AMQP_NS_PER_S;
151 35           time->time_point_ns = now_ns + delta_ns;
152 35 50         if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
    50          
153 0           return AMQP_STATUS_INVALID_PARAMETER;
154             }
155              
156 35           return AMQP_STATUS_OK;
157             }
158              
159 1781           amqp_time_t amqp_time_infinite(void) {
160             amqp_time_t time;
161 1781           time.time_point_ns = UINT64_MAX;
162 1781           return time;
163             }
164              
165 439           int amqp_time_ms_until(amqp_time_t time) {
166             uint64_t now_ns;
167             uint64_t delta_ns;
168             int left_ms;
169              
170 439 100         if (UINT64_MAX == time.time_point_ns) {
171 310           return -1;
172             }
173 129 50         if (0 == time.time_point_ns) {
174 0           return 0;
175             }
176              
177 129           now_ns = amqp_get_monotonic_timestamp();
178 129 50         if (0 == now_ns) {
179 0           return AMQP_STATUS_TIMER_FAILURE;
180             }
181              
182 129 100         if (now_ns >= time.time_point_ns) {
183 3           return 0;
184             }
185              
186 126           delta_ns = time.time_point_ns - now_ns;
187 126           left_ms = (int)(delta_ns / AMQP_NS_PER_MS);
188              
189 126           return left_ms;
190             }
191              
192 76           int amqp_time_tv_until(amqp_time_t time, struct timeval *in,
193             struct timeval **out) {
194             uint64_t now_ns;
195             uint64_t delta_ns;
196              
197 76 50         assert(in != NULL);
198 76 50         if (UINT64_MAX == time.time_point_ns) {
199 0           *out = NULL;
200 0           return AMQP_STATUS_OK;
201             }
202 76 50         if (0 == time.time_point_ns) {
203 0           in->tv_sec = 0;
204 0           in->tv_usec = 0;
205 0           *out = in;
206 0           return AMQP_STATUS_OK;
207             }
208              
209 76           now_ns = amqp_get_monotonic_timestamp();
210 76 50         if (0 == now_ns) {
211 0           return AMQP_STATUS_TIMER_FAILURE;
212             }
213              
214 76 50         if (now_ns >= time.time_point_ns) {
215 0           in->tv_sec = 0;
216 0           in->tv_usec = 0;
217 0           *out = in;
218 0           return AMQP_STATUS_OK;
219             }
220              
221 76           delta_ns = time.time_point_ns - now_ns;
222 76           in->tv_sec = (int)(delta_ns / AMQP_NS_PER_S);
223 76           in->tv_usec = (int)((delta_ns % AMQP_NS_PER_S) / AMQP_NS_PER_US);
224 76           *out = in;
225              
226 76           return AMQP_STATUS_OK;
227             }
228              
229 429           int amqp_time_has_past(amqp_time_t time) {
230             uint64_t now_ns;
231 429 100         if (UINT64_MAX == time.time_point_ns) {
232 417           return AMQP_STATUS_OK;
233             }
234              
235 12           now_ns = amqp_get_monotonic_timestamp();
236 12 50         if (0 == now_ns) {
237 0           return AMQP_STATUS_TIMER_FAILURE;
238             }
239              
240 12 100         if (now_ns > time.time_point_ns) {
241 4           return AMQP_STATUS_TIMEOUT;
242             }
243 8           return AMQP_STATUS_OK;
244             }
245              
246 1281           amqp_time_t amqp_time_first(amqp_time_t l, amqp_time_t r) {
247 1281 100         if (l.time_point_ns < r.time_point_ns) {
248 193           return l;
249             }
250 1088           return r;
251             }
252              
253 10           int amqp_time_equal(amqp_time_t l, amqp_time_t r) {
254 10           return l.time_point_ns == r.time_point_ns;
255             }