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 &timespec() 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