1 // -*- c-basic-offset: 4; related-file-name: "../../lib/timestamp.cc" -*-
2 #ifndef CLICK_TIMESTAMP_HH
3 #define CLICK_TIMESTAMP_HH
4 #include <click/glue.hh>
5 #include <click/type_traits.hh>
6 #include <click/integers.hh>
7 #if !CLICK_LINUXMODULE && !CLICK_BSDMODULE
8 # include <math.h>
9 #endif
10 CLICK_DECLS
11 class String;
12 class Timestamp;
13 Timestamp operator+(Timestamp, const Timestamp &);
14
15 // Timestamp has three possible internal representations, selected by #defines.
16 // * TIMESTAMP_REP_FLAT64: a 64-bit integer number of nanoseconds
17 // * TIMESTAMP_REP_BIG_ENDIAN: 32 bits of seconds plus 32 bits of subseconds
18 // * TIMESTAMP_REP_LITTLE_ENDIAN: 32 bits of subseconds plus 32 bits of seconds
19 //
20 // Rationale: The linuxmodule driver must select the same representation as
21 // Linux's sk_buff tstamp member, which may use any of these representations.
22 // (Linuxmodule Packet objects are equivalent to sk_buffs, and
23 // Packet::timestamp_anno() maps to sk_buff::tstamp. We want to avoid
24 // conversion expense when accessing timestamp_anno(). More seriously, it is
25 // very convenient to treat timestamp_anno() as a modifiable reference.)
26
27 #if !TIMESTAMP_REP_FLAT64 && !TIMESTAMP_REP_BIG_ENDIAN && !TIMESTAMP_REP_LITTLE_ENDIAN
28 # if CLICK_LINUXMODULE
29 # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
30 # define TIMESTAMP_REP_BIG_ENDIAN 1
31 # elif BITS_PER_LONG == 64 || defined(CONFIG_KTIME_SCALAR)
32 # define TIMESTAMP_REP_FLAT64 1
33 # elif defined(__BIG_ENDIAN)
34 # define TIMESTAMP_REP_BIG_ENDIAN 1
35 # else
36 # define TIMESTAMP_REP_LITTLE_ENDIAN 1
37 # endif
38 # elif HAVE_INT64_TYPES && SIZEOF_LONG == 8
39 # define TIMESTAMP_REP_FLAT64 1
40 # elif HAVE_INT64_TYPES && CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN
41 # define TIMESTAMP_REP_LITTLE_ENDIAN 1
42 # else
43 # define TIMESTAMP_REP_BIG_ENDIAN 1
44 # endif
45 #endif
46
47
48 // Timestamp can use microsecond or nanosecond precision. Nanosecond
49 // precision is used if TIMESTAMP_NANOSEC == 1. In the Linux kernel, we
50 // choose what Linux uses for sk_buff::tstamp. Elsewhere, we default to
51 // microsecond precision (XXX); "./configure --enable-nanotimestamp" selects
52 // nanosecond precision.
53
54 #ifndef TIMESTAMP_NANOSEC
55 # if CLICK_LINUXMODULE
56 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
57 # define TIMESTAMP_NANOSEC 1
58 # endif
59 # endif
60 #endif
61
62
63 // Define TIMESTAMP_MATH_FLAT64 if despite a seconds-and-subseconds
64 // representation, 64-bit arithmetic should be used for timestamp addition,
65 // subtraction, and comparisons. This can be faster than operating on two
66 // separate 32-bit integers.
67
68 #if HAVE_INT64_TYPES && !TIMESTAMP_REP_FLAT64
69 # if (TIMESTAMP_REP_BIG_ENDIAN && CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN) \
70 || (TIMESTAMP_REP_LITTLE_ENDIAN && CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN)
71 # define TIMESTAMP_MATH_FLAT64 1
72 # endif
73 #endif
74
75
76 // If a Timestamp's internal representation is identical to struct timespec
77 // or struct timeval, define TIMESTAMP_PUNS_TIMESPEC or TIMESTAMP_PUNS_TIMEVAL.
78
79 #if TIMESTAMP_REP_BIG_ENDIAN
80 # if !TIMESTAMP_NANOSEC && SIZEOF_STRUCT_TIMEVAL == 8
81 # define TIMESTAMP_PUNS_TIMEVAL 1
82 # elif TIMESTAMP_NANOSEC && HAVE_STRUCT_TIMESPEC && SIZEOF_STRUCT_TIMESPEC == 8
83 # define TIMESTAMP_PUNS_TIMESPEC 1
84 # endif
85 #endif
86
87
88 // Timestamp::value_type is the type of arguments to, for example,
89 // Timestamp::make_msec(), and should be as large as possible. This is
90 // int64_t at userlevel. In the linuxmodule driver, int64_t can only be used
91 // if the relevant Linux provides 64-bit divide, which is do_div.
92 // TIMESTAMP_VALUE_INT64 is defined to 1 if Timestamp::value_type is int64_t.
93
94 #if !defined(TIMESTAMP_VALUE_INT64) && HAVE_INT64_TYPES
95 # if CLICK_LINUXMODULE && defined(do_div)
96 # define TIMESTAMP_VALUE_INT64 1
97 # elif !CLICK_LINUXMODULE && !CLICK_BSDMODULE
98 # define TIMESTAMP_VALUE_INT64 1
99 # endif
100 #endif
101
102
103 // PRITIMESTAMP is a printf format string for Timestamps. The corresponding
104 // printf argument list is Timestamp::sec() and Timestamp::subsec(), in that
105 // order.
106
107 #if TIMESTAMP_NANOSEC
108 # define PRITIMESTAMP "%d.%09d"
109 #else
110 # define PRITIMESTAMP "%d.%06d"
111 #endif
112
113
114 // TIMESTAMP_WARPABLE is defined if this Timestamp implementation supports
115 // timewarping.
116
117 #if !CLICK_LINUXMODULE && !CLICK_BSDMODULE && !CLICK_NS
118 # define TIMESTAMP_WARPABLE 1
119 #endif
120
121
122 class Timestamp { public:
123
124 /** @brief Type represents a number of seconds. */
125 typedef int32_t seconds_type;
126 /** @brief Return type for msecval(), usecval(), and nsecval(). */
127 #if TIMESTAMP_VALUE_INT64
128 typedef int64_t value_type;
129 #else
130 typedef int32_t value_type;
131 #endif
132
133 enum {
134 max_seconds = (seconds_type) 2147483647U,
135 /**< Maximum number of seconds representable in a
136 Timestamp. */
137 min_seconds = (seconds_type) -2147483648U
138 /**< Minimum number of seconds representable in a
139 Timestamp. */
140 };
141
142 enum {
143 nsec_per_sec = 1000000000,
144 nsec_per_msec = 1000000,
145 nsec_per_usec = 1000,
146 usec_per_sec = 1000000,
147 usec_per_msec = 1000,
148 msec_per_sec = 1000,
149 #if TIMESTAMP_NANOSEC
150 subsec_per_sec = nsec_per_sec,
151 /**< Number of subseconds in a second. Can be
152 1000000 or 1000000000, depending on how
153 Click is compiled. */
154 #else
155 subsec_per_sec = usec_per_sec,
156 #endif
157 subsec_per_msec = subsec_per_sec / msec_per_sec,
158 subsec_per_usec = subsec_per_sec / usec_per_sec
159 #if CLICK_NS
160 , schedule_granularity = usec_per_sec
161 #endif
162 };
163
164 enum {
165 NSUBSEC = subsec_per_sec
166 };
167
168 typedef uninitialized_type uninitialized_t;
169
170 union rep_t;
171
172
173 /** @brief Construct a zero-valued Timestamp. */
Timestamp()174 inline Timestamp() {
175 assign(0, 0);
176 }
177
178 /** @brief Construct a Timestamp of @a sec seconds plus @a subsec
179 * subseconds.
180 * @param sec number of seconds
181 * @param subsec number of subseconds (defaults to 0)
182 *
183 * The @a subsec parameter must be between 0 and subsec_per_sec - 1, and
184 * the @a sec parameter must be between @link Timestamp::min_seconds
185 * min_seconds @endlink and @link Timestamp::max_seconds max_seconds
186 * @endlink. Errors are not necessarily checked. */
Timestamp(long sec,uint32_t subsec=0)187 explicit inline Timestamp(long sec, uint32_t subsec = 0) {
188 assign(sec, subsec);
189 }
190 /** @overload */
Timestamp(int sec,uint32_t subsec=0)191 explicit inline Timestamp(int sec, uint32_t subsec = 0) {
192 assign(sec, subsec);
193 }
194 /** @overload */
Timestamp(unsigned long sec,uint32_t subsec=0)195 explicit inline Timestamp(unsigned long sec, uint32_t subsec = 0) {
196 assign(sec, subsec);
197 }
198 /** @overload */
Timestamp(unsigned sec,uint32_t subsec=0)199 explicit inline Timestamp(unsigned sec, uint32_t subsec = 0) {
200 assign(sec, subsec);
201 }
202 #if HAVE_FLOAT_TYPES
203 explicit inline Timestamp(double);
204 #endif
205
206 inline Timestamp(const struct timeval &tv);
207 #if HAVE_STRUCT_TIMESPEC
208 inline Timestamp(const struct timespec &ts);
209 #endif
210
211 /** @brief Construct a Timestamp from its internal representation. */
Timestamp(const rep_t & rep)212 inline Timestamp(const rep_t &rep)
213 : _t(rep) {
214 }
215
216 /** @brief Construct an uninitialized timestamp. */
Timestamp(const uninitialized_t & unused)217 inline Timestamp(const uninitialized_t &unused) {
218 (void) unused;
219 }
220
221 typedef seconds_type (Timestamp::*unspecified_bool_type)() const;
222 inline operator unspecified_bool_type() const;
223
224 /** @brief Test if this Timestamp is negative (< Timestamp(0, 0)). */
is_negative() const225 inline bool is_negative() const {
226 #if TIMESTAMP_REP_FLAT64 || TIMESTAMP_MATH_FLAT64
227 return _t.x < 0;
228 #else
229 return sec() < 0;
230 #endif
231 }
232
233 inline seconds_type sec() const;
234 inline uint32_t subsec() const;
235 inline uint32_t msec() const;
236 inline uint32_t usec() const;
237 inline uint32_t nsec() const;
238
239 inline void set_sec(seconds_type sec);
240 inline void set_subsec(uint32_t subsec);
241
242 inline seconds_type msec1() const CLICK_DEPRECATED;
243 inline seconds_type usec1() const CLICK_DEPRECATED;
244 inline seconds_type nsec1() const CLICK_DEPRECATED;
245
246 #if TIMESTAMP_PUNS_TIMEVAL
247 inline const struct timeval &timeval() const;
248 inline const struct timeval &timeval_ceil() const;
249 #else
250 inline struct timeval timeval() const;
251 inline struct timeval timeval_ceil() const;
252 #endif
253 #if HAVE_STRUCT_TIMESPEC
254 # if TIMESTAMP_PUNS_TIMESPEC
255 inline const struct timespec ×pec() const;
256 # else
257 inline struct timespec timespec() const;
258 # endif
259 #endif
260
261 #if HAVE_FLOAT_TYPES
262 inline double doubleval() const;
263 #endif
264 /** @brief Return this timestamp's interval length in milliseconds. */
msecval() const265 inline value_type msecval() const {
266 #if TIMESTAMP_REP_FLAT64
267 return value_div(_t.x, subsec_per_sec / msec_per_sec);
268 #else
269 return (value_type) _t.sec * msec_per_sec + subsec_to_msec(_t.subsec);
270 #endif
271 }
272 /** @brief Return this timestamp's interval length in microseconds. */
usecval() const273 inline value_type usecval() const {
274 #if TIMESTAMP_REP_FLAT64
275 return value_div(_t.x, subsec_per_sec / usec_per_sec);
276 #else
277 return (value_type) _t.sec * usec_per_sec + subsec_to_usec(_t.subsec);
278 #endif
279 }
280 /** @brief Return this timestamp's interval length in nanoseconds. */
nsecval() const281 inline value_type nsecval() const {
282 #if TIMESTAMP_REP_FLAT64
283 return _t.x * (nsec_per_sec / subsec_per_sec);
284 #else
285 return (value_type) _t.sec * nsec_per_sec + subsec_to_nsec(_t.subsec);
286 #endif
287 }
288
289 /** @brief Return the next millisecond-valued timestamp no smaller than *this. */
msec_ceil() const290 inline Timestamp msec_ceil() const {
291 uint32_t x = subsec() % subsec_per_msec;
292 return (x ? *this + Timestamp(0, subsec_per_msec - x) : *this);
293 }
294 /** @brief Return the next microsecond-valued timestamp no smaller than *this. */
usec_ceil() const295 inline Timestamp usec_ceil() const {
296 #if TIMESTAMP_NANOSEC
297 uint32_t x = subsec() % subsec_per_usec;
298 return (x ? *this + Timestamp(0, subsec_per_usec - x) : *this);
299 #else
300 return *this;
301 #endif
302 }
303 /** @brief Return the next nanosecond-valued timestamp no smaller than *this. */
nsec_ceil() const304 inline Timestamp nsec_ceil() const {
305 return *this;
306 }
307
308 #if !CLICK_TOOL
309 /** @brief Return a timestamp representing an interval of @a jiffies. */
310 static inline Timestamp make_jiffies(click_jiffies_t jiffies);
311 /** @overload */
312 static inline Timestamp make_jiffies(click_jiffies_difference_t jiffies);
313 /** @brief Return the number of jiffies represented by this timestamp. */
314 inline click_jiffies_t jiffies() const;
315 #endif
316
317 /** @brief Return a timestamp representing @a sec seconds. */
make_sec(seconds_type sec)318 static inline Timestamp make_sec(seconds_type sec) {
319 return Timestamp(sec, 0);
320 }
321 /** @brief Return a timestamp representing @a sec seconds plus @a msec
322 * milliseconds.
323 * @pre 0 <= @a msec < 1000 */
make_msec(seconds_type sec,uint32_t msec)324 static inline Timestamp make_msec(seconds_type sec, uint32_t msec) {
325 return Timestamp(sec, msec_to_subsec(msec));
326 }
327 /** @brief Return a timestamp representing @a msec milliseconds. */
make_msec(value_type msec)328 static inline Timestamp make_msec(value_type msec) {
329 Timestamp t = Timestamp::uninitialized_t();
330 #if TIMESTAMP_REP_FLAT64
331 t._t.x = msec * (subsec_per_sec / msec_per_sec);
332 #else
333 value_div_mod(t._t.sec, t._t.subsec, msec, msec_per_sec);
334 t._t.subsec *= subsec_per_sec / msec_per_sec;
335 #endif
336 return t;
337 }
338 /** @brief Return a timestamp representing @a sec seconds plus @a usec
339 * microseconds.
340 * @pre 0 <= @a usec < 1000000 */
make_usec(seconds_type sec,uint32_t usec)341 static inline Timestamp make_usec(seconds_type sec, uint32_t usec) {
342 return Timestamp(sec, usec_to_subsec(usec));
343 }
344 /** @brief Return a timestamp representing @a usec microseconds. */
make_usec(value_type usec)345 static inline Timestamp make_usec(value_type usec) {
346 Timestamp t = Timestamp::uninitialized_t();
347 #if TIMESTAMP_REP_FLAT64
348 t._t.x = usec * (subsec_per_sec / usec_per_sec);
349 #else
350 value_div_mod(t._t.sec, t._t.subsec, usec, usec_per_sec);
351 t._t.subsec *= subsec_per_sec / usec_per_sec;
352 #endif
353 return t;
354 }
355 /** @brief Return a timestamp representing @a sec seconds plus @a nsec
356 * nanoseconds.
357 * @pre 0 <= @a nsec < 1000000000 */
make_nsec(seconds_type sec,uint32_t nsec)358 static inline Timestamp make_nsec(seconds_type sec, uint32_t nsec) {
359 return Timestamp(sec, nsec_to_subsec(nsec));
360 }
361 /** @brief Return a timestamp representing @a nsec nanoseconds. */
make_nsec(value_type nsec)362 static inline Timestamp make_nsec(value_type nsec) {
363 Timestamp t = Timestamp::uninitialized_t();
364 #if TIMESTAMP_REP_FLAT64
365 t._t.x = value_div(nsec, nsec_per_sec / subsec_per_sec);
366 #else
367 value_div_mod(t._t.sec, t._t.subsec, nsec, nsec_per_sec);
368 t._t.subsec /= nsec_per_sec / subsec_per_sec;
369 #endif
370 return t;
371 }
372
373
374 /** @brief Return the smallest nonzero timestamp, Timestamp(0, 1). */
epsilon()375 static inline Timestamp epsilon() {
376 return Timestamp(0, 1);
377 }
378
379 /** @brief Clear this timestamp. */
clear()380 inline void clear() {
381 assign(0, 0);
382 }
383
384
385 /** Set this timestamp to a seconds-and-subseconds value.
386 *
387 * @sa Timestamp(int, int) */
assign(seconds_type sec,uint32_t subsec=0)388 inline void assign(seconds_type sec, uint32_t subsec = 0) {
389 #if TIMESTAMP_REP_FLAT64
390 _t.x = (int64_t) sec * subsec_per_sec + subsec;
391 #else
392 _t.sec = sec;
393 _t.subsec = subsec;
394 #endif
395 }
396 /** Assign this timestamp to a seconds-and-microseconds value. */
assign_usec(seconds_type sec,uint32_t usec)397 inline void assign_usec(seconds_type sec, uint32_t usec) {
398 assign(sec, usec_to_subsec(usec));
399 }
400 /** Assign this timestamp to a seconds-and-nanoseconds value. */
assign_nsec(seconds_type sec,uint32_t nsec)401 inline void assign_nsec(seconds_type sec, uint32_t nsec) {
402 assign(sec, nsec_to_subsec(nsec));
403 }
404
405 /** @cond never */
406 /** Assign this timestamp to a seconds-and-subseconds value.
407 * @deprecated Use assign() instead. */
408 inline void set(seconds_type sec, uint32_t subsec = 0) CLICK_DEPRECATED;
409 /** Assign this timestamp to a seconds-and-microseconds value.
410 * @deprecated Use assign_usec() instead. */
411 inline void set_usec(seconds_type sec, uint32_t usec) CLICK_DEPRECATED;
412 /** Assign this timestamp to a seconds-and-nanoseconds value.
413 * @deprecated Use assign_nsec() instead. */
414 inline void set_nsec(seconds_type sec, uint32_t nsec) CLICK_DEPRECATED;
415 /** @brief Deprecated synonym for assign_now().
416 * @deprecated Use Timestamp::assign_now() instead. */
417 inline void set_now() CLICK_DEPRECATED;
418 /** @endcond never */
419 #if !CLICK_LINUXMODULE && !CLICK_BSDMODULE && !CLICK_MINIOS
420 int set_timeval_ioctl(int fd, int ioctl_selector);
421 #endif
422
423
424 /** @brief Return the current system time.
425 *
426 * System time is measured in seconds since January 1, 1970 GMT.
427 * Produces the most precise timestamp available.
428 *
429 * @note System time can jump forwards or backwards as a result of user
430 * actions. For a clock that never moves backwards, see now_steady().
431 * @sa recent(), assign_now(), now_steady() */
432 static inline Timestamp now();
433
434 /** @brief Set this timestamp to the current system time.
435 *
436 * Like "*this = Timestamp::now()".
437 * @sa now(), assign_recent() */
438 inline void assign_now();
439
440 /** @brief Return a recent system time.
441 *
442 * The Timestamp::now() function calculates the current system time, which
443 * is relatively expensive. Timestamp::recent() can be faster, but is
444 * less precise: it returns a cached copy of a recent system time.
445 * @sa now(), assign_recent() */
446 static inline Timestamp recent();
447
448 /** @brief Set this timestamp to a recent system time.
449 *
450 * Like "*this = Timestamp::recent()".
451 * @sa recent(), assign_now() */
452 inline void assign_recent();
453
454
455 /** @brief Return the current steady-clock time.
456 *
457 * The steady clock, often called a monotonic clock, is a system clock
458 * that never moves backwards. Steady-clock time is measured in seconds
459 * since an undefined start point (often related to the most recent boot).
460 * Produces the most precise timestamp available.
461 *
462 * @note Steady-clock times and system times are incomparable, since they
463 * have different start points.
464 *
465 * @sa recent_steady(), assign_now_steady() */
466 static inline Timestamp now_steady();
467
468 /** @brief Set this timestamp to the current steady-clock time.
469 *
470 * Like "*this = Timestamp::now_steady()".
471 * @sa now_steady() */
472 inline void assign_now_steady();
473
474 /** @brief Return a recent steady-clock time.
475 *
476 * The Timestamp::now_steady() function calculates the current
477 * steady-clock time, which is relatively expensive.
478 * Timestamp::recent_steady() can be faster, but is less precise: it
479 * returns a cached copy of a recent steady-clock time.
480 * @sa now_steady(), assign_recent_steady() */
481 static inline Timestamp recent_steady();
482
483 /** @brief Set this timestamp to a recent steady-clock time.
484 *
485 * Like "*this = Timestamp::recent_steady()".
486 * @sa recent_steady(), assign_now_steady() */
487 inline void assign_recent_steady();
488
489
490 /** @brief Unparse this timestamp into a String.
491 *
492 * Returns a string formatted like "10.000000", with at least six
493 * subsecond digits. (Nanosecond-precision timestamps where the number of
494 * nanoseconds is not evenly divisible by 1000 are given nine subsecond
495 * digits.) */
496 String unparse() const;
497
498 /** @brief Unparse this timestamp into a String as an interval.
499 *
500 * Returns a string formatted like "1us" or "1.000002s". */
501 String unparse_interval() const;
502
503
504 /** @brief Convert milliseconds to subseconds.
505 *
506 * Subseconds are either microseconds or nanoseconds, depending on
507 * configuration options and driver choice.
508 * @sa usec_to_subsec(), nsec_to_subsec(), subsec_to_msec(),
509 * subsec_to_usec(), subsec_to_nsec() */
msec_to_subsec(uint32_t msec)510 inline static uint32_t msec_to_subsec(uint32_t msec) {
511 return msec * (subsec_per_sec / msec_per_sec);
512 }
513 /** @brief Convert microseconds to subseconds. */
usec_to_subsec(uint32_t usec)514 inline static uint32_t usec_to_subsec(uint32_t usec) {
515 return usec * (subsec_per_sec / usec_per_sec);
516 }
517 /** @brief Convert nanoseconds to subseconds. */
nsec_to_subsec(uint32_t nsec)518 inline static uint32_t nsec_to_subsec(uint32_t nsec) {
519 return nsec / (nsec_per_sec / subsec_per_sec);
520 }
521 /** @brief Convert subseconds to milliseconds. */
subsec_to_msec(uint32_t subsec)522 inline static uint32_t subsec_to_msec(uint32_t subsec) {
523 return subsec / (subsec_per_sec / msec_per_sec);
524 }
525 /** @brief Convert subseconds to microseconds. */
subsec_to_usec(uint32_t subsec)526 inline static uint32_t subsec_to_usec(uint32_t subsec) {
527 return subsec / (subsec_per_sec / usec_per_sec);
528 }
529 /** @brief Convert subseconds to nanoseconds. */
subsec_to_nsec(uint32_t subsec)530 inline static uint32_t subsec_to_nsec(uint32_t subsec) {
531 return subsec * (nsec_per_sec / subsec_per_sec);
532 }
533
534
535 /** @brief Type of a Timestamp representation.
536 *
537 * This type is rarely useful for Timestamp users; we export it to avoid
538 * strict-aliasing warnings in unions. */
539 union rep_t {
540 #if TIMESTAMP_REP_FLAT64 || TIMESTAMP_MATH_FLAT64
541 int64_t x;
542 #endif
543 #if TIMESTAMP_REP_BIG_ENDIAN
544 struct {
545 int32_t sec;
546 int32_t subsec;
547 };
548 #elif TIMESTAMP_REP_LITTLE_ENDIAN
549 struct {
550 int32_t subsec;
551 int32_t sec;
552 };
553 #endif
554 #if CLICK_LINUXMODULE
555 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
556 ktime_t ktime;
557 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
558 skb_timeval skbtime;
559 # endif
560 #endif
561 #if TIMESTAMP_PUNS_TIMEVAL
562 struct timeval tv;
563 #elif TIMESTAMP_PUNS_TIMESPEC
564 struct timespec tspec;
565 #endif
566 };
567
568 #if TIMESTAMP_WARPABLE
569 /** @name Timewarping */
570 //@{
571 enum warp_class_type {
572 warp_none = 0, ///< Run in real time (the default).
573 warp_linear = 1, ///< Run in speeded-up or slowed-down real time.
574 warp_nowait = 2, ///< Run in speeded-up or slowed-down real time,
575 // but don't wait for timers.
576 warp_simulation = 3 ///< Run in simulation time.
577 };
578
579
580 /** @brief Return the active timewarp class. */
581 static inline int warp_class();
582
583 /** @brief Return the timewarp speed.
584 *
585 * Timewarp speed measures how much faster Timestamp::now() appears to
586 * move compared with wall-clock time. Only meaningful if warp_class() is
587 * #warp_linear or #warp_nowait. */
588 static inline double warp_speed();
589
590
591 /** @brief Set the timewarp class to @a w.
592 * @param w warp class
593 * @param s speed (\> 0, meaningful when @a w == #warp_linear)
594 *
595 * The timewarp classes are as follows:
596 *
597 * <dl>
598 * <dt>#warp_none</dt>
599 * <dd>Click time corresponds to real time. This is the default.</dd>
600 *
601 * <dt>#warp_linear</dt>
602 * <dd>Click time is a speeded-up or slowed-down version of real time.
603 * The speedup factor is @a s. If @a s \> 1, then time as measured by
604 * Timestamp::now() will appear to move a factor of @a s faster than real
605 * time: for instance, a Timer set using Timer::schedule_after_s(2) from
606 * now will fire after just 1 second of wall-clock time.</dd>
607 *
608 * <dt>#warp_nowait</dt>
609 * <dd>Like #warp_linear, but the Click driver never waits for a timer to
610 * expire. Instead, time appears to "jump" ahead to the next expiration
611 * time.</dd>
612 *
613 * <dt>#warp_simulation</dt>
614 * <dd>Click time is completely divorced from real time. Every call to
615 * Timestamp::now() appears to increase the current time by
616 * Timestamp::epsilon() and the Click driver never waits for a timer to
617 * expire. This mode effectively turns Click into an event-driven
618 * simulator.</dd>
619 * </dl>
620 */
621 static void warp_set_class(warp_class_type w, double s = 1.0);
622
623 /** @brief Reset current time.
624 * @a t_system new system time
625 * @a t_steady new steady-clock time
626 *
627 * Only usable when warp_class() is not #warp_none. */
628 static void warp_set_now(const Timestamp &t_system, const Timestamp &t_steady);
629
630
631 /** @brief Return the wall-clock time corresponding to a delay. */
632 inline Timestamp warp_real_delay() const;
633
634 /** @brief Return true iff time skips ahead around timer expirations. */
635 static inline bool warp_jumping();
636
637 /** @brief Move Click time past a timer expiration.
638 *
639 * Does nothing if warp_jumping() is false or @a expiry is in the past. */
640 static void warp_jump_steady(const Timestamp &expiry);
641
642
643 /** @brief Return the warp-free current system time.
644 *
645 * Like now(), but the time returned is unaffected by timewarping.
646 * @sa now(), assign_now_unwarped() */
647 static inline Timestamp now_unwarped();
648
649 /** @brief Set this timestamp to the warp-free current system time.
650 *
651 * Like assign_now(), but the time assigned is unaffected by timewarping.
652 * @sa assign_now(), now_unwarped() */
653 inline void assign_now_unwarped();
654
655 /** @brief Return the warp-free current steady-clock time.
656 *
657 * Like now_steady(), but the time returned is unaffected by timewarping.
658 * @sa now_steady(), assign_now_steady_unwarped() */
659 static inline Timestamp now_steady_unwarped();
660
661 /** @brief Set this timestamp to the warp-free current steady-clock time.
662 *
663 * Like assign_now_steady(), but the time assigned is unaffected by
664 * timewarping.
665 * @sa assign_now_steady(), now_steady_unwarped() */
666 inline void assign_now_steady_unwarped();
667 //@}
668 #endif
669
670 private:
671
672 rep_t _t;
673
add_fix()674 inline void add_fix() {
675 #if TIMESTAMP_REP_FLAT64
676 /* no fix necessary */
677 #elif TIMESTAMP_MATH_FLAT64
678 if (_t.subsec >= subsec_per_sec)
679 _t.x += (uint32_t) -subsec_per_sec;
680 #else
681 if (_t.subsec >= subsec_per_sec)
682 _t.sec++, _t.subsec -= subsec_per_sec;
683 #endif
684 }
685
sub_fix()686 inline void sub_fix() {
687 #if TIMESTAMP_REP_FLAT64
688 /* no fix necessary */
689 #elif TIMESTAMP_MATH_FLAT64
690 if (_t.subsec < 0)
691 _t.subsec += subsec_per_sec;
692 #else
693 if (_t.subsec < 0)
694 _t.sec--, _t.subsec += subsec_per_sec;
695 #endif
696 }
697
value_div(value_type a,uint32_t b)698 static inline value_type value_div(value_type a, uint32_t b) {
699 return int_divide(a, b);
700 }
701
value_div_mod(int32_t & div,int32_t & rem,value_type a,uint32_t b)702 static inline void value_div_mod(int32_t &div, int32_t &rem,
703 value_type a, uint32_t b) {
704 value_type quot;
705 rem = int_remainder(a, b, quot);
706 div = quot;
707 }
708
709 inline void assign_now(bool recent, bool steady, bool unwarped);
710
711 #if TIMESTAMP_WARPABLE
712 static inline void warp_adjust(bool steady, const Timestamp &t_raw, const Timestamp &t_warped);
713 inline Timestamp warped(bool steady) const;
714 void warp(bool steady, bool from_now);
715 #endif
716
717 friend inline bool operator==(const Timestamp &a, const Timestamp &b);
718 friend inline bool operator<(const Timestamp &a, const Timestamp &b);
719 friend inline Timestamp operator-(const Timestamp &b);
720 friend inline Timestamp &operator+=(Timestamp &a, const Timestamp &b);
721 friend inline Timestamp &operator-=(Timestamp &a, const Timestamp &b);
722
723 };
724
725
726 #if TIMESTAMP_WARPABLE
727 /** @cond never */
728 class TimestampWarp {
729 static Timestamp::warp_class_type kind;
730 static double speed;
731 static Timestamp flat_offset[2];
732 static double offset[2];
733 friend class Timestamp;
734 };
735 /** @endcond never */
736
warp_class()737 inline int Timestamp::warp_class() {
738 return TimestampWarp::kind;
739 }
740
warp_speed()741 inline double Timestamp::warp_speed() {
742 return TimestampWarp::speed;
743 }
744
warp_jumping()745 inline bool Timestamp::warp_jumping() {
746 return TimestampWarp::kind >= warp_nowait;
747 }
748
warped(bool steady) const749 inline Timestamp Timestamp::warped(bool steady) const {
750 Timestamp t = *this;
751 if (TimestampWarp::kind)
752 t.warp(steady, false);
753 return t;
754 }
755 #endif
756
757
758 /** @brief Create a Timestamp measuring @a tv.
759 @param tv timeval structure */
760 inline
Timestamp(const struct timeval & tv)761 Timestamp::Timestamp(const struct timeval& tv)
762 {
763 assign(tv.tv_sec, usec_to_subsec(tv.tv_usec));
764 }
765
766 #if HAVE_STRUCT_TIMESPEC
767 /** @brief Create a Timestamp measuring @a ts.
768 @param ts timespec structure */
769 inline
Timestamp(const struct timespec & ts)770 Timestamp::Timestamp(const struct timespec& ts)
771 {
772 assign(ts.tv_sec, nsec_to_subsec(ts.tv_nsec));
773 }
774 #endif
775
776 /** @brief Return true iff this timestamp is not zero-valued. */
777 inline
operator unspecified_bool_type() const778 Timestamp::operator unspecified_bool_type() const
779 {
780 #if TIMESTAMP_REP_FLAT64 || TIMESTAMP_MATH_FLAT64
781 return _t.x ? &Timestamp::sec : 0;
782 #else
783 return _t.sec || _t.subsec ? &Timestamp::sec : 0;
784 #endif
785 }
786
787 inline void
assign_now(bool recent,bool steady,bool unwarped)788 Timestamp::assign_now(bool recent, bool steady, bool unwarped)
789 {
790 (void) recent, (void) steady, (void) unwarped;
791
792 #if TIMESTAMP_PUNS_TIMESPEC
793 # define TIMESTAMP_DECLARE_TSP struct timespec &tsp = _t.tspec
794 # define TIMESTAMP_RESOLVE_TSP /* nothing */
795 #else
796 # define TIMESTAMP_DECLARE_TSP struct timespec ts, &tsp = ts
797 # define TIMESTAMP_RESOLVE_TSP assign(tsp.tv_sec, nsec_to_subsec(tsp.tv_nsec))
798 #endif
799 #if TIMESTAMP_PUNS_TIMEVAL
800 # define TIMESTAMP_DECLARE_TVP struct timeval &tvp = _t.tv
801 # define TIMESTAMP_RESOLVE_TVP /* nothing */
802 #else
803 # define TIMESTAMP_DECLARE_TVP struct timeval tv, &tvp = tv
804 # define TIMESTAMP_RESOLVE_TVP assign(tvp.tv_sec, usec_to_subsec(tvp.tv_usec))
805 #endif
806
807 #if CLICK_LINUXMODULE
808 # if !TIMESTAMP_NANOSEC
809 if (!recent && !steady) {
810 TIMESTAMP_DECLARE_TVP;
811 do_gettimeofday(&tvp);
812 TIMESTAMP_RESOLVE_TVP;
813 return;
814 }
815 # endif
816 TIMESTAMP_DECLARE_TSP;
817 if (recent && steady) {
818 # if HAVE_LINUX_GET_MONOTONIC_COARSE
819 tsp = get_monotonic_coarse();
820 # elif HAVE_LINUX_GETBOOTTIME && HAVE_LINUX_KTIME_MONO_TO_ANY
821 // XXX Is this even worth it????? Would it be faster to just get the
822 // current time?
823 tsp = current_kernel_time();
824 struct timespec delta =
825 ktime_to_timespec(ktime_mono_to_any(ktime_set(0, 0), TK_OFFS_REAL));
826 set_normalized_timespec(&tsp, tsp.tv_sec - delta.tv_sec,
827 tsp.tv_nsec - delta.tv_nsec);
828 # elif HAVE_LINUX_GETBOOTTIME
829 tsp = current_kernel_time();
830 struct timespec delta;
831 getboottime(&delta);
832 monotonic_to_bootbased(&delta);
833 set_normalized_timespec(&tsp, tsp.tv_sec - delta.tv_sec,
834 tsp.tv_nsec - delta.tv_nsec);
835 # else
836 // older kernels don't export enough information to produce a recent
837 // steady timestamp; produce a current steady timestamp
838 ktime_get_ts(&tsp);
839 # endif
840 } else if (recent)
841 tsp = current_kernel_time();
842 else if (steady)
843 ktime_get_ts(&tsp);
844 else
845 getnstimeofday(&tsp);
846 TIMESTAMP_RESOLVE_TSP;
847
848 #elif TIMESTAMP_NANOSEC && CLICK_BSDMODULE
849 TIMESTAMP_DECLARE_TSP;
850 if (recent && steady)
851 getnanouptime(&tsp);
852 else if (recent)
853 getnanotime(&tsp);
854 else if (steady)
855 nanouptime(&tsp);
856 else
857 nanotime(&tsp);
858 TIMESTAMP_RESOLVE_TSP;
859
860 #elif CLICK_BSDMODULE
861 TIMESTAMP_DECLARE_TVP;
862 if (recent && steady)
863 getmicrouptime(&tvp);
864 else if (recent)
865 getmicrotime(&tvp);
866 else if (steady)
867 microuptime(&tvp);
868 else
869 microtime(&tvp);
870 TIMESTAMP_RESOLVE_TVP;
871
872 #elif CLICK_MINIOS
873 TIMESTAMP_DECLARE_TVP;
874 gettimeofday(&tvp, (struct timezone *) 0);
875 TIMESTAMP_RESOLVE_TVP;
876
877 #elif CLICK_NS
878 if (schedule_granularity == usec_per_sec) {
879 TIMESTAMP_DECLARE_TVP;
880 simclick_gettimeofday(&tvp);
881 TIMESTAMP_RESOLVE_TVP;
882 } else {
883 assert(0 && "nanosecond precision not available yet");
884 }
885
886 #elif HAVE_USE_CLOCK_GETTIME
887 TIMESTAMP_DECLARE_TSP;
888 if (steady)
889 clock_gettime(CLOCK_MONOTONIC, &tsp);
890 else
891 clock_gettime(CLOCK_REALTIME, &tsp);
892 TIMESTAMP_RESOLVE_TSP;
893
894 #else
895 TIMESTAMP_DECLARE_TVP;
896 gettimeofday(&tvp, (struct timezone *) 0);
897 TIMESTAMP_RESOLVE_TVP;
898 #endif
899
900 #undef TIMESTAMP_DECLARE_TSP
901 #undef TIMESTAMP_RESOLVE_TSP
902 #undef TIMESTAMP_DECLARE_TVP
903 #undef TIMESTAMP_RESOLVE_TVP
904
905 #if TIMESTAMP_WARPABLE
906 // timewarping
907 if (!unwarped && TimestampWarp::kind)
908 warp(steady, true);
909 #endif
910 }
911
912 inline void
assign_now()913 Timestamp::assign_now()
914 {
915 assign_now(false, false, false);
916 }
917
918 inline Timestamp
now()919 Timestamp::now()
920 {
921 Timestamp t = Timestamp::uninitialized_t();
922 t.assign_now();
923 return t;
924 }
925
926 inline void
assign_recent()927 Timestamp::assign_recent()
928 {
929 assign_now(true, false, false);
930 }
931
932 inline Timestamp
recent()933 Timestamp::recent()
934 {
935 Timestamp t = Timestamp::uninitialized_t();
936 t.assign_recent();
937 return t;
938 }
939
940 inline void
assign_now_steady()941 Timestamp::assign_now_steady()
942 {
943 assign_now(false, true, false);
944 }
945
946 inline Timestamp
now_steady()947 Timestamp::now_steady()
948 {
949 Timestamp t = Timestamp::uninitialized_t();
950 t.assign_now_steady();
951 return t;
952 }
953
954 inline void
assign_recent_steady()955 Timestamp::assign_recent_steady()
956 {
957 assign_now(true, true, false);
958 }
959
960 inline Timestamp
recent_steady()961 Timestamp::recent_steady()
962 {
963 Timestamp t = Timestamp::uninitialized_t();
964 t.assign_recent_steady();
965 return t;
966 }
967
968 #if TIMESTAMP_WARPABLE
969 inline void
assign_now_unwarped()970 Timestamp::assign_now_unwarped()
971 {
972 assign_now(false, false, true);
973 }
974
975 inline Timestamp
now_unwarped()976 Timestamp::now_unwarped()
977 {
978 Timestamp t = Timestamp::uninitialized_t();
979 t.assign_now_unwarped();
980 return t;
981 }
982
983 inline void
assign_now_steady_unwarped()984 Timestamp::assign_now_steady_unwarped()
985 {
986 assign_now(false, true, true);
987 }
988
989 inline Timestamp
now_steady_unwarped()990 Timestamp::now_steady_unwarped()
991 {
992 Timestamp t = Timestamp::uninitialized_t();
993 t.assign_now_steady_unwarped();
994 return t;
995 }
996 #endif
997
998 /** @brief Set this timestamp's seconds component.
999
1000 The subseconds component is left unchanged. */
1001 inline void
set_sec(seconds_type sec)1002 Timestamp::set_sec(seconds_type sec)
1003 {
1004 #if TIMESTAMP_REP_FLAT64
1005 uint32_t ss = subsec();
1006 _t.x = (int64_t) sec * subsec_per_sec + ss;
1007 #else
1008 _t.sec = sec;
1009 #endif
1010 }
1011
1012 /** @brief Set this timestamp's subseconds component.
1013 @param subsec number of subseconds
1014
1015 The seconds component is left unchanged. */
1016 inline void
set_subsec(uint32_t subsec)1017 Timestamp::set_subsec(uint32_t subsec)
1018 {
1019 #if TIMESTAMP_REP_FLAT64
1020 seconds_type s = sec();
1021 _t.x = (int64_t) s * subsec_per_sec + subsec;
1022 #else
1023 _t.subsec = subsec;
1024 #endif
1025 }
1026
1027 /** @brief Return this timestamp's seconds component. */
1028 inline Timestamp::seconds_type
sec() const1029 Timestamp::sec() const
1030 {
1031 #if TIMESTAMP_REP_FLAT64
1032 if (unlikely(_t.x < 0))
1033 return -value_div(-(_t.x + 1), subsec_per_sec) - 1;
1034 else
1035 return value_div(_t.x, subsec_per_sec);
1036 #else
1037 return _t.sec;
1038 #endif
1039 }
1040
1041 /** @brief Return this timestamp's subseconds component. */
1042 inline uint32_t
subsec() const1043 Timestamp::subsec() const
1044 {
1045 #if TIMESTAMP_REP_FLAT64
1046 return _t.x - (uint32_t) sec() * subsec_per_sec;
1047 #else
1048 return _t.subsec;
1049 #endif
1050 }
1051
1052 /** @brief Return this timestamp's subseconds component, converted to
1053 milliseconds. */
1054 inline uint32_t
msec() const1055 Timestamp::msec() const
1056 {
1057 return subsec_to_msec(subsec());
1058 }
1059
1060 /** @brief Return this timestamp's subseconds component, converted to
1061 microseconds. */
1062 inline uint32_t
usec() const1063 Timestamp::usec() const
1064 {
1065 return subsec_to_usec(subsec());
1066 }
1067
1068 /** @brief Return this timestamp's subseconds component, converted to
1069 nanoseconds. */
1070 inline uint32_t
nsec() const1071 Timestamp::nsec() const
1072 {
1073 return subsec_to_nsec(subsec());
1074 }
1075
1076 /** @brief Return this timestamp's interval length, converted to
1077 milliseconds.
1078
1079 Will overflow on intervals of more than 2147483.647 seconds. */
1080 inline Timestamp::seconds_type
msec1() const1081 Timestamp::msec1() const
1082 {
1083 #if TIMESTAMP_REP_FLAT64
1084 return value_div(_t.x, subsec_per_sec / msec_per_sec);
1085 #else
1086 return _t.sec * msec_per_sec + subsec_to_msec(_t.subsec);
1087 #endif
1088 }
1089
1090 /** @brief Return this timestamp's interval length, converted to
1091 microseconds.
1092
1093 Will overflow on intervals of more than 2147.483647 seconds. */
1094 inline Timestamp::seconds_type
usec1() const1095 Timestamp::usec1() const
1096 {
1097 #if TIMESTAMP_REP_FLAT64
1098 return value_div(_t.x, subsec_per_sec / usec_per_sec);
1099 #else
1100 return _t.sec * usec_per_sec + subsec_to_usec(_t.subsec);
1101 #endif
1102 }
1103
1104 /** @brief Return this timestamp's interval length, converted to
1105 nanoseconds.
1106
1107 Will overflow on intervals of more than 2.147483647 seconds. */
1108 inline Timestamp::seconds_type
nsec1() const1109 Timestamp::nsec1() const
1110 {
1111 #if TIMESTAMP_REP_FLAT64
1112 return _t.x * (nsec_per_sec / subsec_per_sec);
1113 #else
1114 return _t.sec * nsec_per_sec + subsec_to_nsec(_t.subsec);
1115 #endif
1116 }
1117
1118 #if !CLICK_TOOL
1119 inline click_jiffies_t
jiffies() const1120 Timestamp::jiffies() const
1121 {
1122 # if TIMESTAMP_REP_FLAT64
1123 // This is not very precise when CLICK_HZ doesn't divide NSUBSEC evenly.
1124 return value_div(_t.x, subsec_per_sec / CLICK_HZ);
1125 # else
1126 click_jiffies_t j = ((click_jiffies_t) sec()) * CLICK_HZ;
1127 # if CLICK_HZ == 100 || CLICK_HZ == 1000 || CLICK_HZ == 10000 || CLICK_HZ == 100000 || CLICK_HZ == 1000000
1128 return j + ((click_jiffies_t) subsec()) / (subsec_per_sec / CLICK_HZ);
1129 # else
1130 // This is not very precise when CLICK_HZ doesn't divide NSUBSEC evenly.
1131 return j + ((click_jiffies_t) subsec()) / (subsec_per_sec / CLICK_HZ);
1132 # endif
1133 # endif
1134 }
1135
1136 inline Timestamp
make_jiffies(click_jiffies_t jiffies)1137 Timestamp::make_jiffies(click_jiffies_t jiffies)
1138 {
1139 // Not very precise when CLICK_HZ doesn't evenly divide subsec_per_sec.
1140 Timestamp t = Timestamp::uninitialized_t();
1141 # if TIMESTAMP_REP_FLAT64
1142 t._t.x = (int64_t) jiffies * (subsec_per_sec / CLICK_HZ);
1143 # else
1144 t._t.sec = jiffies / CLICK_HZ;
1145 t._t.subsec = (jiffies - t._t.sec * CLICK_HZ) * (subsec_per_sec / CLICK_HZ);
1146 # endif
1147 return t;
1148 }
1149
1150 inline Timestamp
make_jiffies(click_jiffies_difference_t jiffies)1151 Timestamp::make_jiffies(click_jiffies_difference_t jiffies)
1152 {
1153 // Not very precise when CLICK_HZ doesn't evenly divide subsec_per_sec.
1154 Timestamp t = Timestamp::uninitialized_t();
1155 # if TIMESTAMP_REP_FLAT64
1156 t._t.x = (int64_t) jiffies * (subsec_per_sec / CLICK_HZ);
1157 # else
1158 if (jiffies < 0)
1159 t._t.sec = -(-(jiffies + 1) / CLICK_HZ) - 1;
1160 else
1161 t._t.sec = jiffies / CLICK_HZ;
1162 t._t.subsec = (jiffies - t._t.sec * CLICK_HZ) * (subsec_per_sec / CLICK_HZ);
1163 # endif
1164 return t;
1165 }
1166 #endif
1167
1168 /** @cond never */
set_now()1169 inline void Timestamp::set_now() {
1170 assign_now(false, false, false);
1171 }
1172
set(seconds_type sec,uint32_t subsec)1173 inline void Timestamp::set(seconds_type sec, uint32_t subsec) {
1174 assign(sec, subsec);
1175 }
1176
set_usec(seconds_type sec,uint32_t usec)1177 inline void Timestamp::set_usec(seconds_type sec, uint32_t usec) {
1178 assign_usec(sec, usec);
1179 }
1180
set_nsec(seconds_type sec,uint32_t nsec)1181 inline void Timestamp::set_nsec(seconds_type sec, uint32_t nsec) {
1182 assign_nsec(sec, nsec);
1183 }
1184 /** @endcond never */
1185
1186 /** @relates Timestamp
1187 @brief Compare two timestamps for equality.
1188
1189 Returns true iff the two operands have the same seconds and subseconds
1190 components. */
1191 inline bool
operator ==(const Timestamp & a,const Timestamp & b)1192 operator==(const Timestamp &a, const Timestamp &b)
1193 {
1194 #if TIMESTAMP_REP_FLAT64 || TIMESTAMP_MATH_FLAT64
1195 return a._t.x == b._t.x;
1196 #else
1197 return a.sec() == b.sec() && a.subsec() == b.subsec();
1198 #endif
1199 }
1200
1201 /** @relates Timestamp
1202 @brief Compare two timestamps for inequality.
1203
1204 Returns true iff !(@a a == @a b). */
1205 inline bool
operator !=(const Timestamp & a,const Timestamp & b)1206 operator!=(const Timestamp &a, const Timestamp &b)
1207 {
1208 return !(a == b);
1209 }
1210
1211 /** @relates Timestamp
1212 @brief Compare two timestamps.
1213
1214 Returns true iff @a a represents a shorter interval than @a b, or
1215 considered as absolute time, @a a happened before @a b. */
1216 inline bool
operator <(const Timestamp & a,const Timestamp & b)1217 operator<(const Timestamp &a, const Timestamp &b)
1218 {
1219 #if TIMESTAMP_REP_FLAT64 || TIMESTAMP_MATH_FLAT64
1220 return a._t.x < b._t.x;
1221 #else
1222 return a.sec() < b.sec() || (a.sec() == b.sec() && a.subsec() < b.subsec());
1223 #endif
1224 }
1225
1226 /** @overload */
1227 inline bool
operator <(const Timestamp & a,int b)1228 operator<(const Timestamp &a, int b)
1229 {
1230 return a < Timestamp(b);
1231 }
1232
1233 /** @relates Timestamp
1234 @brief Compare two timestamps.
1235
1236 Returns true iff @a a measures an interval no larger than @a b, or
1237 considered as absolute time, @a a happened at or before @a b. */
1238 inline bool
operator <=(const Timestamp & a,const Timestamp & b)1239 operator<=(const Timestamp &a, const Timestamp &b)
1240 {
1241 return !(b < a);
1242 }
1243
1244 /** @overload */
1245 inline bool
operator <=(const Timestamp & a,int b)1246 operator<=(const Timestamp &a, int b)
1247 {
1248 return a <= Timestamp(b);
1249 }
1250
1251 /** @relates Timestamp
1252 @brief Compare two timestamps.
1253
1254 Returns true iff @a a measures an interval no shorter than @a b, or
1255 considered as absolute time, @a a happened at or after @a b. */
1256 inline bool
operator >=(const Timestamp & a,const Timestamp & b)1257 operator>=(const Timestamp &a, const Timestamp &b)
1258 {
1259 return !(a < b);
1260 }
1261
1262 /** @overload */
1263 inline bool
operator >=(const Timestamp & a,int b)1264 operator>=(const Timestamp &a, int b)
1265 {
1266 return a >= Timestamp(b);
1267 }
1268
1269 /** @relates Timestamp
1270 @brief Compare two timestamps.
1271
1272 Returns true iff @a a measures a longer interval than @a b, or considered
1273 as absolute time, @a a happened after @a b. */
1274 inline bool
operator >(const Timestamp & a,const Timestamp & b)1275 operator>(const Timestamp &a, const Timestamp &b)
1276 {
1277 return b < a;
1278 }
1279
1280 /** @overload */
1281 inline bool
operator >(const Timestamp & a,int b)1282 operator>(const Timestamp &a, int b)
1283 {
1284 return a > Timestamp(b);
1285 }
1286
1287 /** @brief Add @a b to @a a.
1288
1289 Returns the result (the new value of @a a). */
1290 inline Timestamp &
operator +=(Timestamp & a,const Timestamp & b)1291 operator+=(Timestamp &a, const Timestamp &b)
1292 {
1293 #if TIMESTAMP_REP_FLAT64 || TIMESTAMP_MATH_FLAT64
1294 a._t.x += b._t.x;
1295 #else
1296 a._t.sec += b._t.sec;
1297 a._t.subsec += b._t.subsec;
1298 #endif
1299 a.add_fix();
1300 return a;
1301 }
1302
1303 /** @brief Subtract @a b from @a a.
1304
1305 Returns the result (the new value of @a a). */
1306 inline Timestamp &
operator -=(Timestamp & a,const Timestamp & b)1307 operator-=(Timestamp &a, const Timestamp &b)
1308 {
1309 #if TIMESTAMP_REP_FLAT64 || TIMESTAMP_MATH_FLAT64
1310 a._t.x -= b._t.x;
1311 #else
1312 a._t.sec -= b._t.sec;
1313 a._t.subsec -= b._t.subsec;
1314 #endif
1315 a.sub_fix();
1316 return a;
1317 }
1318
1319 /** @brief Add the two operands and return the result. */
1320 inline Timestamp
operator +(Timestamp a,const Timestamp & b)1321 operator+(Timestamp a, const Timestamp &b)
1322 {
1323 a += b;
1324 return a;
1325 }
1326
1327 /** @brief Subtract @a b from @a a and return the result. */
1328 inline Timestamp
operator -(Timestamp a,const Timestamp & b)1329 operator-(Timestamp a, const Timestamp &b)
1330 {
1331 a -= b;
1332 return a;
1333 }
1334
1335 /** @brief Negate @a a and return the result. */
1336 inline Timestamp
operator -(const Timestamp & a)1337 operator-(const Timestamp &a)
1338 {
1339 #if TIMESTAMP_REP_FLAT64
1340 Timestamp t = Timestamp::uninitialized_t();
1341 t._t.x = -a._t.x;
1342 return t;
1343 #else
1344 if (a.subsec())
1345 return Timestamp(-(a.sec() + 1), Timestamp::subsec_per_sec - a.subsec());
1346 else
1347 return Timestamp(-a.sec(), 0);
1348 #endif
1349 }
1350
1351 #if HAVE_FLOAT_TYPES
1352 /** @brief Return this timestamp's value, converted to a real number. */
1353 inline double
doubleval() const1354 Timestamp::doubleval() const
1355 {
1356 # if TIMESTAMP_REP_FLAT64
1357 return _t.x / (double) subsec_per_sec;
1358 # else
1359 return _t.sec + (_t.subsec / (double) subsec_per_sec);
1360 # endif
1361 }
1362
1363 /** @brief Create a timestamp measuring @a d seconds. */
1364 inline
Timestamp(double d)1365 Timestamp::Timestamp(double d)
1366 {
1367 # if TIMESTAMP_REP_FLAT64
1368 _t.x = (int64_t) floor(d * subsec_per_sec + 0.5);
1369 # else
1370 double dfloor = floor(d);
1371 _t.sec = (seconds_type) dfloor;
1372 _t.subsec = (uint32_t) ((d - dfloor) * subsec_per_sec + 0.5);
1373 add_fix();
1374 # endif
1375 }
1376
1377 /** @brief Scale @a a by a factor of @a b and return the result. */
1378 inline Timestamp
operator *(const Timestamp & a,double b)1379 operator*(const Timestamp &a, double b)
1380 {
1381 return Timestamp(a.doubleval() * b);
1382 }
1383
1384 inline Timestamp
operator *(const Timestamp & a,int b)1385 operator*(const Timestamp &a, int b)
1386 {
1387 return Timestamp(a.doubleval() * b);
1388 }
1389
1390 inline Timestamp
operator *(const Timestamp & a,unsigned b)1391 operator*(const Timestamp &a, unsigned b)
1392 {
1393 return Timestamp(a.doubleval() * b);
1394 }
1395
1396 inline Timestamp
operator *(double a,const Timestamp & b)1397 operator*(double a, const Timestamp &b)
1398 {
1399 return Timestamp(b.doubleval() * a);
1400 }
1401
1402 inline Timestamp
operator *(int a,const Timestamp & b)1403 operator*(int a, const Timestamp &b)
1404 {
1405 return Timestamp(b.doubleval() * a);
1406 }
1407
1408 inline Timestamp
operator *(unsigned a,const Timestamp & b)1409 operator*(unsigned a, const Timestamp &b)
1410 {
1411 return Timestamp(b.doubleval() * a);
1412 }
1413
1414 /** @brief Scale @a a down by a factor of @a b and return the result. */
1415 inline Timestamp
operator /(const Timestamp & a,double b)1416 operator/(const Timestamp &a, double b)
1417 {
1418 return Timestamp(a.doubleval() / b);
1419 }
1420
1421 inline Timestamp
operator /(const Timestamp & a,int b)1422 operator/(const Timestamp &a, int b)
1423 {
1424 return Timestamp(a.doubleval() / b);
1425 }
1426
1427 inline Timestamp
operator /(const Timestamp & a,unsigned b)1428 operator/(const Timestamp &a, unsigned b)
1429 {
1430 return Timestamp(a.doubleval() / b);
1431 }
1432
1433 /** @brief Divide @a a by @a b and return the result. */
1434 inline double
operator /(const Timestamp & a,const Timestamp & b)1435 operator/(const Timestamp &a, const Timestamp &b)
1436 {
1437 return a.doubleval() / b.doubleval();
1438 }
1439 #endif /* HAVE_FLOAT_TYPES */
1440
1441 StringAccum& operator<<(StringAccum&, const Timestamp&);
1442
1443 #if TIMESTAMP_WARPABLE
1444 inline Timestamp
warp_real_delay() const1445 Timestamp::warp_real_delay() const
1446 {
1447 if (likely(!TimestampWarp::kind) || TimestampWarp::speed == 1.0)
1448 return *this;
1449 else
1450 return *this / TimestampWarp::speed;
1451 }
1452 #endif
1453
1454 #if TIMESTAMP_PUNS_TIMEVAL
1455 inline const struct timeval &
timeval() const1456 Timestamp::timeval() const
1457 {
1458 return _t.tv;
1459 }
1460
1461 inline const struct timeval &
timeval_ceil() const1462 Timestamp::timeval_ceil() const
1463 {
1464 return _t.tv;
1465 }
1466 #else
1467 /** @brief Return a struct timeval that approximates this timestamp.
1468
1469 If Timestamp and struct timeval have the same size and representation,
1470 then this operation returns a "const struct timeval &" whose address is
1471 the same as this Timestamp. If Timestamps have nanosecond precision,
1472 the conversion rounds down, so Timestamp(t.timeval()) <= t. */
1473 inline struct timeval
timeval() const1474 Timestamp::timeval() const
1475 {
1476 struct timeval tv;
1477 tv.tv_sec = sec();
1478 tv.tv_usec = usec();
1479 return tv;
1480 }
1481
1482 /** @brief Return the minimum struct timeval >= this timestamp.
1483
1484 If Timestamp and struct timeval have the same size and representation,
1485 then this operation returns a "const struct timeval &" whose address is
1486 the same as this Timestamp. */
1487 inline struct timeval
timeval_ceil() const1488 Timestamp::timeval_ceil() const
1489 {
1490 return (*this + Timestamp(0, subsec_per_usec - 1)).timeval();
1491 }
1492 #endif
1493
1494 #if HAVE_STRUCT_TIMESPEC
1495 # if TIMESTAMP_PUNS_TIMESPEC
1496 inline const struct timespec &
timespec() const1497 Timestamp::timespec() const
1498 {
1499 return _t.tspec;
1500 }
1501 # else
1502 /** @brief Return a struct timespec with the same value as this timestamp.
1503
1504 If Timestamp and struct timespec have the same size and representation,
1505 then this operation returns a "const struct timespec &" whose address is
1506 the same as this Timestamp. */
1507 inline struct timespec
timespec() const1508 Timestamp::timespec() const
1509 {
1510 struct timespec ts;
1511 ts.tv_sec = sec();
1512 ts.tv_nsec = nsec();
1513 return ts;
1514 }
1515 # endif
1516 #endif
1517
1518
1519 class ArgContext;
1520 extern const ArgContext blank_args;
1521 bool cp_time(const String &str, Timestamp *result, bool allow_negative);
1522
1523 /** @class TimestampArg
1524 @brief Parser class for timestamps. */
1525 class TimestampArg { public:
TimestampArg(bool is_signed=false)1526 TimestampArg(bool is_signed = false)
1527 : is_signed(is_signed) {
1528 }
parse(const String & str,Timestamp & value,const ArgContext & args=blank_args)1529 bool parse(const String &str, Timestamp &value, const ArgContext &args = blank_args) {
1530 (void) args;
1531 return cp_time(str, &value, is_signed);
1532 }
1533 bool is_signed;
1534 };
1535
1536 template<> struct DefaultArg<Timestamp> : public TimestampArg {};
1537 template<> struct has_trivial_copy<Timestamp> : public true_type {};
1538
1539 CLICK_ENDDECLS
1540 #endif
1541