File Coverage

amqp_time.c
Criterion Covered Total %
statement 73 93 78.4
branch 36 56 64.2
condition n/a
subroutine n/a
pod n/a
total 109 149 73.1


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 359           uint64_t amqp_get_monotonic_timestamp(void) {
91             #ifdef __hpux
92             return (uint64_t)gethrtime();
93             #else
94             struct timespec tp;
95 359 50         if (-1 == clock_gettime(CLOCK_MONOTONIC, &tp)) {
96 0           return 0;
97             }
98              
99 359           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 461           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 461 50         assert(NULL != time);
109              
110 461 100         if (NULL == timeout) {
111 341           *time = amqp_time_infinite();
112 341           return AMQP_STATUS_OK;
113             }
114 120 100         if (0 == timeout->tv_sec && 0 == timeout->tv_usec) {
    50          
115 2           *time = amqp_time_immediate();
116 2           return AMQP_STATUS_OK;
117             }
118              
119 118 50         if (timeout->tv_sec < 0 || timeout->tv_usec < 0) {
    50          
120 0           return AMQP_STATUS_INVALID_PARAMETER;
121             }
122              
123 236           delta_ns = (uint64_t)timeout->tv_sec * AMQP_NS_PER_S +
124 118           (uint64_t)timeout->tv_usec * AMQP_NS_PER_US;
125              
126 118           now_ns = amqp_get_monotonic_timestamp();
127 118 50         if (0 == now_ns) {
128 0           return AMQP_STATUS_TIMER_FAILURE;
129             }
130              
131 118           time->time_point_ns = now_ns + delta_ns;
132 118 50         if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
    50          
133 0           return AMQP_STATUS_INVALID_PARAMETER;
134             }
135              
136 118           return AMQP_STATUS_OK;
137             }
138              
139 1010           int amqp_time_s_from_now(amqp_time_t *time, int seconds) {
140             uint64_t now_ns;
141             uint64_t delta_ns;
142 1010 50         assert(NULL != time);
143              
144 1010 100         if (0 >= seconds) {
145 976           *time = amqp_time_infinite();
146 976           return AMQP_STATUS_OK;
147             }
148              
149 34           now_ns = amqp_get_monotonic_timestamp();
150 34 50         if (0 == now_ns) {
151 0           return AMQP_STATUS_TIMER_FAILURE;
152             }
153              
154 34           delta_ns = (uint64_t)seconds * AMQP_NS_PER_S;
155 34           time->time_point_ns = now_ns + delta_ns;
156 34 50         if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
    50          
157 0           return AMQP_STATUS_INVALID_PARAMETER;
158             }
159              
160 34           return AMQP_STATUS_OK;
161             }
162              
163 4           amqp_time_t amqp_time_immediate(void) {
164             amqp_time_t time;
165 4           time.time_point_ns = 0;
166 4           return time;
167             }
168              
169 1788           amqp_time_t amqp_time_infinite(void) {
170             amqp_time_t time;
171 1788           time.time_point_ns = UINT64_MAX;
172 1788           return time;
173             }
174              
175 438           int amqp_time_ms_until(amqp_time_t time) {
176             uint64_t now_ns;
177             uint64_t delta_ns;
178             int left_ms;
179              
180 438 100         if (UINT64_MAX == time.time_point_ns) {
181 314           return -1;
182             }
183 124 100         if (0 == time.time_point_ns) {
184 2           return 0;
185             }
186              
187 122           now_ns = amqp_get_monotonic_timestamp();
188 122 50         if (0 == now_ns) {
189 0           return AMQP_STATUS_TIMER_FAILURE;
190             }
191              
192 122 50         if (now_ns >= time.time_point_ns) {
193 0           return 0;
194             }
195              
196 122           delta_ns = time.time_point_ns - now_ns;
197 122           left_ms = (int)(delta_ns / AMQP_NS_PER_MS);
198              
199 122           return left_ms;
200             }
201              
202 74           int amqp_time_tv_until(amqp_time_t time, struct timeval *in,
203             struct timeval **out) {
204             uint64_t now_ns;
205             uint64_t delta_ns;
206              
207 74 50         assert(in != NULL);
208 74 50         if (UINT64_MAX == time.time_point_ns) {
209 0           *out = NULL;
210 0           return AMQP_STATUS_OK;
211             }
212 74 50         if (0 == time.time_point_ns) {
213 0           in->tv_sec = 0;
214 0           in->tv_usec = 0;
215 0           *out = in;
216 0           return AMQP_STATUS_OK;
217             }
218              
219 74           now_ns = amqp_get_monotonic_timestamp();
220 74 50         if (0 == now_ns) {
221 0           return AMQP_STATUS_TIMER_FAILURE;
222             }
223              
224 74 50         if (now_ns >= time.time_point_ns) {
225 0           in->tv_sec = 0;
226 0           in->tv_usec = 0;
227 0           *out = in;
228 0           return AMQP_STATUS_OK;
229             }
230              
231 74           delta_ns = time.time_point_ns - now_ns;
232 74           in->tv_sec = (int)(delta_ns / AMQP_NS_PER_S);
233 74           in->tv_usec = (int)((delta_ns % AMQP_NS_PER_S) / AMQP_NS_PER_US);
234 74           *out = in;
235              
236 74           return AMQP_STATUS_OK;
237             }
238              
239 426           int amqp_time_has_past(amqp_time_t time) {
240             uint64_t now_ns;
241 426 100         if (UINT64_MAX == time.time_point_ns) {
242 415           return AMQP_STATUS_OK;
243             }
244              
245 11           now_ns = amqp_get_monotonic_timestamp();
246 11 50         if (0 == now_ns) {
247 0           return AMQP_STATUS_TIMER_FAILURE;
248             }
249              
250 11 100         if (now_ns > time.time_point_ns) {
251 4           return AMQP_STATUS_TIMEOUT;
252             }
253 7           return AMQP_STATUS_OK;
254             }
255              
256 1278           amqp_time_t amqp_time_first(amqp_time_t l, amqp_time_t r) {
257 1278 100         if (l.time_point_ns < r.time_point_ns) {
258 187           return l;
259             }
260 1091           return r;
261             }
262              
263 8           int amqp_time_equal(amqp_time_t l, amqp_time_t r) {
264 8           return l.time_point_ns == r.time_point_ns;
265             }