1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2005,2006 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20 #ifndef TIME_H
21 #define TIME_H
22
23 #include "assert.h"
24 #include "attribute.h"
25 #include "attribute-helper.h"
26 #include "event-id.h"
27 #include "int64x64.h"
28 #include "unused.h"
29 #include <stdint.h>
30 #include <limits>
31 #include <cmath>
32 #include <ostream>
33 #include <set>
34
35 /**
36 * \file
37 * \ingroup time
38 * Declaration of classes ns3::Time and ns3::TimeWithUnit,
39 * and the TimeValue implementation classes.
40 */
41
42 namespace ns3 {
43
44 class TimeWithUnit;
45
46 /**
47 * \ingroup core
48 * \defgroup time Virtual Time
49 * Management of virtual time in real world units.
50 *
51 * The underlying simulator is unit agnostic, just dealing with
52 * dimensionless virtual time. Models usually need to handle
53 * time in real world units, such as seconds, and conversions/scaling
54 * between different units, between minutes and seconds, for example.
55 *
56 * The convenience constructors in the \ref timecivil "Standard Units" module
57 * make it easy to create Times in specific units.
58 *
59 * The Time::SetResolution() function allows a one-time change of the
60 * base resolution, before Simulator::Run().
61 */
62 /**
63 * \ingroup time
64 * Simulation virtual time values and global simulation resolution.
65 *
66 * This class defines all the classic C++ addition/subtraction
67 * operators: +, -, +=, -=; and all the classic comparison operators:
68 * ==, !=, <, >, <=, >=. It is thus easy to add, subtract, or
69 * compare Time objects.
70 *
71 * For example:
72 * \code
73 * Time t1 = Seconds (10.0);
74 * Time t2 = Seconds (10.0);
75 * Time t3 = t1;
76 * t3 += t2;
77 * \endcode
78 *
79 * You can also use the following non-member functions to manipulate
80 * any of these ns3::Time object:
81 * - Abs(Time)
82 * - Max(Time,Time)
83 * - Min(Time,Time)
84 *
85 * This class also controls the resolution of the underlying time representation.
86 * The resolution is the smallest representable time interval.
87 * The default resolution is nanoseconds.
88 *
89 * To change the resolution, use SetResolution(). All Time objects created
90 * before the call to SetResolution() will be updated to the new resolution.
91 * This can only be done once! (Tracking each Time object uses 4 pointers.
92 * For speed, once we convert the existing instances we discard the recording
93 * data structure and stop tracking new instances, so we have no way
94 * to do a second conversion.)
95 *
96 * If you increase the global resolution, you also implicitly decrease
97 * the maximum simulation duration. The global simulation time is stored
98 * in a 64 bit integer whose interpretation will depend on the global
99 * resolution. Therefore the maximum possible duration of your simulation
100 * if you use picoseconds is 2^64 ps = 2^24 s = 7 months, whereas,
101 * had you used nanoseconds, you could have run for 584 years.
102 */
103 class Time
104 {
105 public:
106 /**
107 * The unit to use to interpret a number representing time
108 */
109 enum Unit
110 {
111 Y = 0, //!< year, 365 days
112 D = 1, //!< day, 24 hours
113 H = 2, //!< hour, 60 minutes
114 MIN = 3, //!< minute, 60 seconds
115 S = 4, //!< second
116 MS = 5, //!< millisecond
117 US = 6, //!< microsecond
118 NS = 7, //!< nanosecond
119 PS = 8, //!< picosecond
120 FS = 9, //!< femtosecond
121 LAST = 10, //!< marker for last normal value
122 AUTO = 11 //!< auto-scale output when using Time::As()
123 };
124
125 /**
126 * Assignment operator
127 * \param [in] o Time to assign.
128 * \return The Time.
129 */
130 inline Time & operator = (const Time & o)
131 {
132 m_data = o.m_data;
133 return *this;
134 }
135 /** Default constructor, with value 0. */
Time()136 inline Time ()
137 : m_data ()
138 {
139 if (g_markingTimes)
140 {
141 Mark (this);
142 }
143 }
144 /**
145 * Copy constructor
146 *
147 * \param [in] o Time to copy
148 */
Time(const Time & o)149 inline Time (const Time & o)
150 : m_data (o.m_data)
151 {
152 if (g_markingTimes)
153 {
154 Mark (this);
155 }
156 }
157
158 /**
159 * Move constructor
160 *
161 * \param [in] o Time from which take the data
162 */
Time(Time && o)163 Time (Time &&o)
164 : m_data (o.m_data)
165 {
166 if (g_markingTimes)
167 {
168 Mark (this);
169 }
170 }
171 /**
172 * \name Numeric constructors
173 * Construct from a numeric value.
174 * @{
175 */
176 /**
177 * Construct from a numeric value.
178 * The current time resolution will be assumed as the unit.
179 * \param [in] v The value.
180 */
Time(double v)181 explicit inline Time (double v)
182 : m_data (lround (v))
183 {
184 if (g_markingTimes)
185 {
186 Mark (this);
187 }
188 }
Time(int v)189 explicit inline Time (int v)
190 : m_data (v)
191 {
192 if (g_markingTimes)
193 {
194 Mark (this);
195 }
196 }
Time(long int v)197 explicit inline Time (long int v)
198 : m_data (v)
199 {
200 if (g_markingTimes)
201 {
202 Mark (this);
203 }
204 }
Time(long long int v)205 explicit inline Time (long long int v)
206 : m_data (v)
207 {
208 if (g_markingTimes)
209 {
210 Mark (this);
211 }
212 }
Time(unsigned int v)213 explicit inline Time (unsigned int v)
214 : m_data (v)
215 {
216 if (g_markingTimes)
217 {
218 Mark (this);
219 }
220 }
Time(unsigned long int v)221 explicit inline Time (unsigned long int v)
222 : m_data (v)
223 {
224 if (g_markingTimes)
225 {
226 Mark (this);
227 }
228 }
Time(unsigned long long int v)229 explicit inline Time (unsigned long long int v)
230 : m_data (v)
231 {
232 if (g_markingTimes)
233 {
234 Mark (this);
235 }
236 }
Time(const int64x64_t & v)237 explicit inline Time (const int64x64_t & v)
238 : m_data (v.Round ())
239 {
240 if (g_markingTimes)
241 {
242 Mark (this);
243 }
244 }
245 /**@}*/ // Numeric constructors
246
247 /**
248 * Construct Time object from common time expressions like "1ms"
249 *
250 * Supported units include:
251 * - `s` (seconds)
252 * - `ms` (milliseconds)
253 * - `us` (microseconds)
254 * - `ns` (nanoseconds)
255 * - `ps` (picoseconds)
256 * - `fs` (femtoseconds)
257 * - `min` (minutes)
258 * - `h` (hours)
259 * - `d` (days)
260 * - `y` (years)
261 *
262 * There can be no white space between the numerical portion
263 * and the units. Any otherwise malformed string causes a fatal error to
264 * occur.
265 * \param [in] s The string to parse into a Time
266 */
267 explicit Time (const std::string & s);
268
269 /**
270 * Minimum representable Time
271 * Not to be confused with Min(Time,Time).
272 * \returns the minimum representable Time.
273 */
Min()274 static Time Min ()
275 {
276 return Time (std::numeric_limits<int64_t>::min ());
277 }
278 /**
279 * Maximum representable Time
280 * Not to be confused with Max(Time,Time).
281 * \returns the maximum representable Time.
282 */
Max()283 static Time Max ()
284 {
285 return Time (std::numeric_limits<int64_t>::max ());
286 }
287
288 /** Destructor */
~Time()289 ~Time ()
290 {
291 if (g_markingTimes)
292 {
293 Clear (this);
294 }
295 }
296
297 /**
298 * Exactly equivalent to `t == 0`.
299 * \return \c true if the time is zero, \c false otherwise.
300 */
IsZero(void)301 inline bool IsZero (void) const
302 {
303 return m_data == 0;
304 }
305 /**
306 * Exactly equivalent to `t <= 0`.
307 * \return \c true if the time is negative or zero, \c false otherwise.
308 */
IsNegative(void)309 inline bool IsNegative (void) const
310 {
311 return m_data <= 0;
312 }
313 /**
314 * Exactly equivalent to `t >= 0`.
315 * \return \c true if the time is positive or zero, \c false otherwise.
316 */
IsPositive(void)317 inline bool IsPositive (void) const
318 {
319 return m_data >= 0;
320 }
321 /**
322 * Exactly equivalent to `t < 0`.
323 * \return \c true if the time is strictly negative, \c false otherwise.
324 */
IsStrictlyNegative(void)325 inline bool IsStrictlyNegative (void) const
326 {
327 return m_data < 0;
328 }
329 /**
330 * Exactly equivalent to `t > 0`.
331 * \return \c true if the time is strictly positive, \c false otherwise.
332 */
IsStrictlyPositive(void)333 inline bool IsStrictlyPositive (void) const
334 {
335 return m_data > 0;
336 }
337 /**
338 * Compare \pname{this} to another Time
339 *
340 * \param [in] o The other Time
341 * \return -1,0,+1 if `this < o`, `this == o`, or `this > o`
342 */
Compare(const Time & o)343 inline int Compare (const Time & o) const
344 {
345 return (m_data < o.m_data) ? -1 : (m_data == o.m_data) ? 0 : 1;
346 }
347
348 /**
349 * \name Convert to Number in a Unit
350 * Convert a Time to number, in indicated units.
351 *
352 * Conversions to seconds and larger will return doubles, with
353 * possible loss of precision. Conversions to units smaller than
354 * seconds will be rounded.
355 *
356 * @{
357 */
358 /**
359 * Get an approximation of the time stored in this instance
360 * in the indicated unit.
361 *
362 * \return An approximate value in the indicated unit.
363 */
GetYears(void)364 inline double GetYears (void) const
365 {
366 return ToDouble (Time::Y);
367 }
GetDays(void)368 inline double GetDays (void) const
369 {
370 return ToDouble (Time::D);
371 }
GetHours(void)372 inline double GetHours (void) const
373 {
374 return ToDouble (Time::H);
375 }
GetMinutes(void)376 inline double GetMinutes (void) const
377 {
378 return ToDouble (Time::MIN);
379 }
GetSeconds(void)380 inline double GetSeconds (void) const
381 {
382 return ToDouble (Time::S);
383 }
GetMilliSeconds(void)384 inline int64_t GetMilliSeconds (void) const
385 {
386 return ToInteger (Time::MS);
387 }
GetMicroSeconds(void)388 inline int64_t GetMicroSeconds (void) const
389 {
390 return ToInteger (Time::US);
391 }
GetNanoSeconds(void)392 inline int64_t GetNanoSeconds (void) const
393 {
394 return ToInteger (Time::NS);
395 }
GetPicoSeconds(void)396 inline int64_t GetPicoSeconds (void) const
397 {
398 return ToInteger (Time::PS);
399 }
GetFemtoSeconds(void)400 inline int64_t GetFemtoSeconds (void) const
401 {
402 return ToInteger (Time::FS);
403 }
404 /**@}*/ // Convert to Number in a Unit.
405
406 /**
407 * \name Convert to Raw Value
408 * Convert a Time to a number in the current resolution units.
409 *
410 * @{
411 */
412 /**
413 * Get the raw time value, in the current resolution unit.
414 * \returns The raw time value
415 */
GetTimeStep(void)416 inline int64_t GetTimeStep (void) const
417 {
418 return m_data;
419 }
GetDouble(void)420 inline double GetDouble (void) const
421 {
422 return static_cast<double> (m_data);
423 }
GetInteger(void)424 inline int64_t GetInteger (void) const
425 {
426 return GetTimeStep ();
427 }
428 /**@}*/ // Convert to Raw Value
429
430
431 /**
432 * \param [in] resolution The new resolution to use
433 *
434 * Change the global resolution used to convert all
435 * user-provided time values in Time objects and Time objects
436 * in user-expected time units.
437 */
438 static void SetResolution (enum Unit resolution);
439 /**
440 * \returns The current global resolution.
441 */
442 static enum Unit GetResolution (void);
443
444
445 /**
446 * Create a Time in the current unit.
447 *
448 * \param [in] value The value of the new Time.
449 * \return A Time with \pname{value} in the current time unit.
450 */
From(const int64x64_t & value)451 inline static Time From (const int64x64_t & value)
452 {
453 return Time (value);
454 }
455 /**
456 * \name Create Times from Values and Units
457 * Create Times from values given in the indicated units.
458 *
459 * @{
460 */
461 /**
462 * Create a Time equal to \pname{value} in unit \c unit
463 *
464 * \param [in] value The new Time value, expressed in \c unit
465 * \param [in] unit The unit of \pname{value}
466 * \return The Time representing \pname{value} in \c unit
467 */
FromInteger(uint64_t value,enum Unit unit)468 inline static Time FromInteger (uint64_t value, enum Unit unit)
469 {
470 struct Information *info = PeekInformation (unit);
471 if (info->fromMul)
472 {
473 value *= info->factor;
474 }
475 else
476 {
477 value /= info->factor;
478 }
479 return Time (value);
480 }
FromDouble(double value,enum Unit unit)481 inline static Time FromDouble (double value, enum Unit unit)
482 {
483 return From (int64x64_t (value), unit);
484 }
From(const int64x64_t & value,enum Unit unit)485 inline static Time From (const int64x64_t & value, enum Unit unit)
486 {
487 struct Information *info = PeekInformation (unit);
488 // DO NOT REMOVE this temporary variable. It's here
489 // to work around a compiler bug in gcc 3.4
490 int64x64_t retval = value;
491 if (info->fromMul)
492 {
493 retval *= info->timeFrom;
494 }
495 else
496 {
497 retval.MulByInvert (info->timeFrom);
498 }
499 return Time (retval);
500 }
501 /**@}*/ // Create Times from Values and Units
502
503
504 /**
505 * \name Get Times as Numbers in Specified Units
506 * Get the Time as integers or doubles in the indicated unit.
507 *
508 * @{
509 */
510 /**
511 * Get the Time value expressed in a particular unit.
512 *
513 * \param [in] unit The desired unit
514 * \return The Time expressed in \pname{unit}
515 */
ToInteger(enum Unit unit)516 inline int64_t ToInteger (enum Unit unit) const
517 {
518 struct Information *info = PeekInformation (unit);
519 int64_t v = m_data;
520 if (info->toMul)
521 {
522 v *= info->factor;
523 }
524 else
525 {
526 v /= info->factor;
527 }
528 return v;
529 }
ToDouble(enum Unit unit)530 inline double ToDouble (enum Unit unit) const
531 {
532 return To (unit).GetDouble ();
533 }
To(enum Unit unit)534 inline int64x64_t To (enum Unit unit) const
535 {
536 struct Information *info = PeekInformation (unit);
537 int64x64_t retval = int64x64_t (m_data);
538 if (info->toMul)
539 {
540 retval *= info->timeTo;
541 }
542 else
543 {
544 retval.MulByInvert (info->timeTo);
545 }
546 return retval;
547 }
548 /**@}*/ // Get Times as Numbers in Specified Units
549
550 /**
551 * Round a Time to a specific unit.
552 * Rounding is to nearest integer.
553 * \return The Time rounded to the specific unit.
554 */
RoundTo(enum Unit unit)555 Time RoundTo (enum Unit unit) const
556 {
557 return From (this->To (unit).Round (), unit);
558 }
559
560 /**
561 * Attach a unit to a Time, to facilitate output in a specific unit.
562 *
563 * For example,
564 * \code
565 * Time t (3.14e9); // Pi seconds
566 * std::cout << t.As (Time::MS) << std::endl;
567 * \endcode
568 * will print ``+3140.0ms``
569 *
570 * \param [in] unit The unit to use.
571 * \return The Time with embedded unit.
572 */
573 TimeWithUnit As (const enum Unit unit = Time::AUTO) const;
574
575 /**
576 * TracedCallback signature for Time
577 *
578 * \param [in] value Current value of Time
579 */
580 typedef void (* TracedCallback)(Time value);
581
582 private:
583 /** How to convert between other units and the current unit. */
584 struct Information
585 {
586 bool toMul; //!< Multiply when converting To, otherwise divide
587 bool fromMul; //!< Multiple when converting From, otherwise divide
588 int64_t factor; //!< Ratio of this unit / current unit
589 int64x64_t timeTo; //!< Multiplier to convert to this unit
590 int64x64_t timeFrom; //!< Multiplier to convert from this unit
591 };
592 /** Current time unit, and conversion info. */
593 struct Resolution
594 {
595 struct Information info[LAST]; //!< Conversion info from current unit
596 enum Time::Unit unit; //!< Current time unit
597 };
598
599 /**
600 * Get the current Resolution
601 *
602 * \return A pointer to the current Resolution
603 */
PeekResolution(void)604 static inline struct Resolution * PeekResolution (void)
605 {
606 static struct Time::Resolution resolution = SetDefaultNsResolution ();
607 return &resolution;
608 }
609 /**
610 * Get the Information record for \pname{timeUnit} for the current Resolution
611 *
612 * \param [in] timeUnit The Unit to get Information for
613 * \return The Information for \pname{timeUnit}
614 */
PeekInformation(enum Unit timeUnit)615 static inline struct Information * PeekInformation (enum Unit timeUnit)
616 {
617 return &(PeekResolution ()->info[timeUnit]);
618 }
619
620 /**
621 * Set the default resolution
622 *
623 * \return The Resolution object for the default resolution.
624 */
625 static struct Resolution SetDefaultNsResolution (void);
626 /**
627 * Set the current Resolution.
628 *
629 * \param [in] unit The unit to use as the new resolution.
630 * \param [in,out] resolution The Resolution record to update.
631 * \param [in] convert Whether to convert existing Time objects to the new resolution.
632 */
633 static void SetResolution (enum Unit unit, struct Resolution *resolution,
634 const bool convert = true);
635
636 /**
637 * Record all instances of Time, so we can rescale them when
638 * the resolution changes.
639 *
640 * \internal
641 *
642 * We use a std::set so we can remove the record easily when
643 * ~Time() is called.
644 *
645 * We don't use Ptr<Time>, because we would have to bloat every Time
646 * instance with SimpleRefCount<Time>.
647 *
648 * Seems like this should be std::set< Time * const >, but
649 * [Stack Overflow](http://stackoverflow.com/questions/5526019/compile-errors-stdset-with-const-members)
650 * says otherwise, quoting the standard:
651 *
652 * > & sect;23.1/3 states that std::set key types must be assignable
653 * > and copy constructable; clearly a const type will not be assignable.
654 */
655 typedef std::set< Time * > MarkedTimes;
656 /**
657 * Record of outstanding Time objects which will need conversion
658 * when the resolution is set.
659 *
660 * \internal
661 *
662 * Use a classic static variable so we can check in Time ctors
663 * without a function call.
664 *
665 * We'd really like to initialize this here, but we don't want to require
666 * C++0x, so we init in time.cc. To ensure that happens before first use,
667 * we add a call to StaticInit (below) to every compilation unit which
668 * includes nstime.h.
669 */
670 static MarkedTimes * g_markingTimes;
671
672 public:
673 /**
674 * Function to force static initialization of Time.
675 *
676 * \return \c true on the first call
677 */
678 static bool StaticInit ();
679 private:
680 /**
681 * \cond HIDE_FROM_DOXYGEN
682 * Doxygen bug throws a warning here, so hide from Doxygen.
683 *
684 * Friend the Simulator class so it can call the private function
685 * ClearMarkedTimes ()
686 */
687 friend class Simulator;
688 /** \endcond */
689
690 /**
691 * Remove all MarkedTimes.
692 *
693 * \internal
694 * Has to be visible to the Simulator class, hence the friending.
695 */
696 static void ClearMarkedTimes ();
697 /**
698 * Record a Time instance with the MarkedTimes.
699 * \param [in] time The Time instance to record.
700 */
701 static void Mark (Time * const time);
702 /**
703 * Remove a Time instance from the MarkedTimes, called by ~Time().
704 * \param [in] time The Time instance to remove.
705 */
706 static void Clear (Time * const time);
707 /**
708 * Convert existing Times to the new unit.
709 * \param [in] unit The Unit to convert existing Times to.
710 */
711 static void ConvertTimes (const enum Unit unit);
712
713
714 // Operator and related functions which need access
715
716 /**
717 * \name Comparison operators
718 * @{
719 */
720 friend bool operator == (const Time & lhs, const Time & rhs);
721 friend bool operator != (const Time & lhs, const Time & rhs);
722 friend bool operator <= (const Time & lhs, const Time & rhs);
723 friend bool operator >= (const Time & lhs, const Time & rhs);
724 friend bool operator < (const Time & lhs, const Time & rhs);
725 friend bool operator > (const Time & lhs, const Time & rhs);
726 friend bool operator < (const Time & time, const EventId & event);
727 /**@}*/
728 /**
729 * \name Arithmetic operators
730 * @{
731 */
732 friend Time operator + (const Time & lhs, const Time & rhs);
733 friend Time operator - (const Time & lhs, const Time & rhs);
734 friend Time operator * (const Time & lhs, const int64x64_t & rhs);
735 friend Time operator * (const int64x64_t & lhs, const Time & rhs);
736
737 template<class T>
738 friend typename std::enable_if<std::is_integral<T>::value, Time>::type
739 operator * (const Time& lhs, T rhs);
740
741 //this function uses is_arithmetic because it can be used by both
742 //integers and decimal types
743 /**
744 * Limited to \c is_arithmetic matches for the T argument to reduce the chances
745 * of matching some arbitrary object type.
746 */
747 template<class T>
748 friend typename std::enable_if<std::is_arithmetic<T>::value, Time>::type
749 operator * (T lhs, const Time& rhs);
750
751 template<class T>
752 friend typename std::enable_if<std::is_floating_point<T>::value, Time>::type
753 operator * (const Time& lhs, T rhs);
754
755 friend int64x64_t operator / (const Time & lhs, const Time & rhs);
756 friend Time operator / (const Time & lhs, const int64x64_t & rhs);
757
758 template<class T>
759 friend typename std::enable_if<std::is_integral<T>::value, Time>::type
760 operator / (const Time& lhs, T rhs);
761
762 template<class T>
763 friend typename std::enable_if<std::is_floating_point<T>::value, Time>::type
764 operator / (const Time& lhs, T rhs);
765
766 friend Time operator % (const Time & lhs, const Time & rhs);
767 friend int64_t Div (const Time & lhs, const Time & rhs);
768 friend Time Rem (const Time & lhs, const Time & rhs);
769
770 /**@}*/
771 /**
772 * \name Compound assignment operators
773 * @{
774 */
775 friend Time & operator += (Time & lhs, const Time & rhs);
776 friend Time & operator -= (Time & lhs, const Time & rhs);
777 /**@}*/
778
779 /**
780 * Absolute value function for Time
781 * \param [in] time The input value
782 * \returns The absolute value of the input value
783 */
784 friend Time Abs (const Time & time);
785 /**
786 * Max function for Time.
787 * \param [in] timeA The first value
788 * \param [in] timeB The seconds value
789 * \returns The max of the two input values.
790 */
791 friend Time Max (const Time & timeA, const Time & timeB);
792 /**
793 * Min function for Time.
794 * \param [in] timeA The first value
795 * \param [in] timeB The seconds value
796 * \returns The min of the two input values.
797 */
798 friend Time Min (const Time & timeA, const Time & timeB);
799
800
801 int64_t m_data; //!< Virtual time value, in the current unit.
802
803 }; // class Time
804
805 namespace TracedValueCallback {
806
807 /**
808 * TracedValue callback signature for Time
809 *
810 * \param [in] oldValue Original value of the traced variable
811 * \param [in] newValue New value of the traced variable
812 */
813 typedef void (* Time)(Time oldValue, Time newValue);
814
815 } // namespace TracedValueCallback
816
817 /**
818 * Force static initialization order of Time in each compilation unit.
819 * This is internal to the Time implementation.
820 * \relates Time
821 */
822 static bool NS_UNUSED_GLOBAL (g_TimeStaticInit) = Time::StaticInit ();
823
824 /**
825 * Equality operator for Time.
826 * \param [in] lhs The first value
827 * \param [in] rhs The second value
828 * \returns \c true if the two input values are equal.
829 */
830 inline bool
831 operator == (const Time & lhs, const Time & rhs)
832 {
833 return lhs.m_data == rhs.m_data;
834 }
835 /**
836 * Inequality operator for Time.
837 * \param [in] lhs The first value
838 * \param [in] rhs The second value
839 * \returns \c true if the two input values not are equal.
840 */
841 inline bool
842 operator != (const Time & lhs, const Time & rhs)
843 {
844 return lhs.m_data != rhs.m_data;
845 }
846 /**
847 * Less than or equal operator for Time.
848 * \param [in] lhs The first value
849 * \param [in] rhs The second value
850 * \returns \c true if the first input value is less than or equal to the second input value.
851 */
852 inline bool
853 operator <= (const Time & lhs, const Time & rhs)
854 {
855 return lhs.m_data <= rhs.m_data;
856 }
857 /**
858 * Greater than or equal operator for Time.
859 * \param [in] lhs The first value
860 * \param [in] rhs The second value
861 * \returns \c true if the first input value is greater than or equal to the second input value.
862 */
863 inline bool
864 operator >= (const Time & lhs, const Time & rhs)
865 {
866 return lhs.m_data >= rhs.m_data;
867 }
868 /**
869 * Less than operator for Time.
870 * \param [in] lhs The first value
871 * \param [in] rhs The second value
872 * \returns \c true if the first input value is less than the second input value.
873 */
874 inline bool
875 operator < (const Time & lhs, const Time & rhs)
876 {
877 return lhs.m_data < rhs.m_data;
878 }
879 /**
880 * Greater than operator for Time.
881 * \param [in] lhs The first value
882 * \param [in] rhs The second value
883 * \returns \c true if the first input value is greater than the second input value.
884 */
885 inline bool
886 operator > (const Time & lhs, const Time & rhs)
887 {
888 return lhs.m_data > rhs.m_data;
889 }
890 /**
891 * Compare a Time to an EventId.
892 *
893 * This is useful when you have cached a previously scheduled event:
894 *
895 * m_event = Schedule (...);
896 *
897 * and later you want to know the relationship between that event
898 * and some other Time `when`:
899 *
900 * if (when < m_event) ...
901 *
902 * \param [in] time The Time operand.
903 * \param [in] event The EventId
904 * \returns \c true if \p time is before (less than) the
905 * time stamp of the EventId.
906 */
907 inline bool
908 operator < (const Time & time, const EventId & event)
909 {
910 // Negative Time is less than any possible EventId, which are all >= 0.
911 if (time.m_data < 0)
912 {
913 return true;
914 }
915 // Time must be >= 0 so casting to unsigned is safe.
916 return static_cast<uint64_t> (time.m_data) < event.GetTs ();
917 }
918 /**
919 * Addition operator for Time.
920 * \param [in] lhs The first value
921 * \param [in] rhs The second value
922 * \returns The sum of the two input values.
923 */
924 inline Time operator + (const Time & lhs, const Time & rhs)
925 {
926 return Time (lhs.m_data + rhs.m_data);
927 }
928 /**
929 * Subtraction operator for Time.
930 * \param [in] lhs The first value
931 * \param [in] rhs The second value
932 * \returns The difference of the two input values.
933 */
934 inline Time operator - (const Time & lhs, const Time & rhs)
935 {
936 return Time (lhs.m_data - rhs.m_data);
937 }
938
939 /**
940 * Scale a Time by a numeric value.
941 * \param [in] lhs The first value
942 * \param [in] rhs The second value
943 * \returns The Time scaled by the other operand.
944 */
945 inline Time
946 operator * (const Time & lhs, const int64x64_t & rhs)
947 {
948 int64x64_t res = lhs.m_data;
949 res *= rhs;
950 return Time (res);
951 }
952 /**
953 * Scale a Time by a numeric value.
954 * \param [in] lhs The first value
955 * \param [in] rhs The second value
956 * \returns The Time scaled by the other operand.
957 */
958 inline Time
959 operator * (const int64x64_t & lhs, const Time & rhs)
960 {
961 return rhs * lhs;
962 }
963
964 /**
965 * Scale a Time by an integer value.
966 *
967 * \tparam T Integer data type (int, long, etc.)
968 *
969 * \param [in] lhs The Time instance to scale
970 * \param [in] rhs The scale value
971 * \returns A new Time instance containing the scaled value
972 */
973 template<class T>
974 typename std::enable_if<std::is_integral<T>::value, Time>::type
975 operator * (const Time& lhs, T rhs)
976 {
977 static_assert(!std::is_same<T, bool>::value,
978 "Multiplying a Time by a boolean is not supported");
979
980 return Time (lhs.m_data * rhs);
981 }
982
983 /**
984 * Scale a Time by a numeric value.
985 *
986 * This overload handles the case where the scale value comes before the Time
987 * value. It swaps the arguments so that the Time argument comes first
988 * and calls the appropriate overload of operator*
989 *
990 * \tparam T Arithmetic data type (int, long, float, etc.)
991 *
992 * \param [in] lhs The scale value
993 * \param [in] rhs The Time instance to scale
994 * \returns A new Time instance containing the scaled value
995 */
996 template<class T>
997 typename std::enable_if<std::is_arithmetic<T>::value, Time>::type
998 operator * (T lhs, const Time& rhs)
999 {
1000 return rhs * lhs;
1001 }
1002
1003 /**
1004 * Scale a Time by a floating point value.
1005 *
1006 * \tparam T Floating point data type (float, double, etc.)
1007 *
1008 * \param [in] lhs The scale value
1009 * \param [in] rhs The Time instance to scale
1010 * \returns A new Time instance containing the scaled value
1011 */
1012 template<class T>
1013 typename std::enable_if<std::is_floating_point<T>::value, Time>::type
1014 operator * (const Time& lhs, T rhs)
1015 {
1016 return lhs * int64x64_t(rhs);
1017 }
1018
1019 /**
1020 * Exact division, returning a dimensionless fixed point number.
1021 *
1022 * This can be truncated to integer, or converted to double
1023 * (with loss of precison). Assuming `ta` and `tb` are Times:
1024 *
1025 * \code
1026 * int64x64_t ratio = ta / tb;
1027 *
1028 * int64_t i = ratio.GetHigh (); // Get just the integer part, resulting in truncation
1029 *
1030 * double ratioD = double (ratio); // Convert to double, with loss of precision
1031 * \endcode
1032 *
1033 * \param [in] lhs The first value
1034 * \param [in] rhs The second value
1035 * \returns The exact ratio of the two operands.
1036 */
1037 inline int64x64_t
1038 operator / (const Time & lhs, const Time & rhs)
1039 {
1040 int64x64_t num = lhs.m_data;
1041 int64x64_t den = rhs.m_data;
1042 return num / den;
1043 }
1044
1045 /**
1046 * Scale a Time by a numeric value.
1047 * \param [in] lhs The first value
1048 * \param [in] rhs The second value
1049 * \returns The Time divided by the scalar operand.
1050 */
1051 inline Time
1052 operator / (const Time & lhs, const int64x64_t & rhs)
1053 {
1054 int64x64_t res = lhs.m_data;
1055 res /= rhs;
1056 return Time (res);
1057 }
1058
1059 /**
1060 * Divide a Time by an integer value.
1061 *
1062 * \tparam T Integer data type (int, long, etc.)
1063 *
1064 * \param [in] lhs The Time instance to scale
1065 * \param [in] rhs The scale value
1066 * \returns A new Time instance containing the scaled value
1067 */
1068 template<class T>
1069 typename std::enable_if<std::is_integral<T>::value, Time>::type
1070 operator / (const Time& lhs, T rhs)
1071 {
1072 static_assert(!std::is_same<T, bool>::value,
1073 "Dividing a Time by a boolean is not supported");
1074
1075 return Time(lhs.m_data / rhs);
1076 }
1077
1078 /**
1079 * Divide a Time by a floating point value.
1080 *
1081 * \tparam T Floating point data type (float, double, etc.)
1082 *
1083 * \param [in] lhs The Time instance to scale
1084 * \param [in] rhs The scale value
1085 * \returns A new Time instance containing the scaled value
1086 */
1087 template<class T>
1088 typename std::enable_if<std::is_floating_point<T>::value, Time>::type
1089 operator / (const Time& lhs, T rhs)
1090 {
1091 return lhs / int64x64_t(rhs);
1092 }
1093
1094 /**
1095 * Remainder (modulus) from the quotient of two Times.
1096 *
1097 * This is exactly the same function as Rem()
1098 *
1099 * Rem (ta, tb) == ta % tb;
1100 *
1101 * \see Div()
1102 * \param [in] lhs The first time value
1103 * \param [in] rhs The second time value
1104 * \returns The remainder of `lhs / rhs`.
1105 */
1106 inline Time
1107 operator % (const Time & lhs, const Time & rhs)
1108 {
1109 return Time (lhs.m_data % rhs.m_data);
1110 }
1111 /**
1112 * Integer quotient from dividing two Times.
1113 *
1114 * This is the same as the "normal" C++ integer division,
1115 * which truncates (discarding any remainder).
1116 *
1117 * As usual, if `ta`, and `tb` are both Times
1118 *
1119 * \code
1120 * ta == tb * Div (ta, tb) + Rem (ta, tb);
1121 *
1122 * ta == tb * (ta / tb).GetHigh() + ta % tb;
1123 * \endcode
1124 *
1125 * \param [in] lhs The first value
1126 * \param [in] rhs The second value
1127 * \returns The integer portion of `lhs / rhs`.
1128 *
1129 * \see Rem()
1130 */
1131 inline int64_t
Div(const Time & lhs,const Time & rhs)1132 Div (const Time & lhs, const Time & rhs)
1133 {
1134 return lhs.m_data / rhs.m_data;
1135 }
1136 /**
1137 * Remainder (modulus) from the quotient of two Times.
1138 *
1139 * This is exactly the same function as operator%()
1140 *
1141 * Rem (ta, tb) == ta % tb;
1142 *
1143 * \see Div()
1144 * \param [in] lhs The first time value
1145 * \param [in] rhs The second time value
1146 * \returns The result of the remainder of the first input / second input value.
1147 */
1148 inline Time
Rem(const Time & lhs,const Time & rhs)1149 Rem (const Time & lhs, const Time & rhs)
1150 {
1151 return Time (lhs.m_data % rhs.m_data);
1152 }
1153
1154 /**
1155 * Compound addition assignment for Time.
1156 * \param [in] lhs The first value
1157 * \param [in] rhs The second value
1158 * \returns The sum of the two inputs.
1159 */
1160 inline Time & operator += (Time & lhs, const Time & rhs)
1161 {
1162 lhs.m_data += rhs.m_data;
1163 return lhs;
1164 }
1165 /**
1166 * Compound subtraction assignment for Time.
1167 * \param [in] lhs The first value
1168 * \param [in] rhs The second value
1169 * \returns The difference of the two operands.
1170 */
1171 inline Time & operator -= (Time & lhs, const Time & rhs)
1172 {
1173 lhs.m_data -= rhs.m_data;
1174 return lhs;
1175 }
1176 /**
1177 * Absolute value for Time.
1178 * \param [in] time The Time value
1179 * \returns The absolute value of the input.
1180 */
Abs(const Time & time)1181 inline Time Abs (const Time & time)
1182 {
1183 return Time ((time.m_data < 0) ? -time.m_data : time.m_data);
1184 }
1185 /**
1186 * Maximum of two Times.
1187 * \param [in] timeA The first value
1188 * \param [in] timeB The second value
1189 * \returns The larger of the two operands.
1190 */
Max(const Time & timeA,const Time & timeB)1191 inline Time Max (const Time & timeA, const Time & timeB)
1192 {
1193 return Time ((timeA.m_data < timeB.m_data) ? timeB : timeA);
1194 }
1195 /**
1196 * Minimum of two Times.
1197 * \param [in] timeA The first value
1198 * \param [in] timeB The second value
1199 * \returns The smaller of the two operands.
1200 */
Min(const Time & timeA,const Time & timeB)1201 inline Time Min (const Time & timeA, const Time & timeB)
1202 {
1203 return Time ((timeA.m_data > timeB.m_data) ? timeB : timeA);
1204 }
1205
1206 /**
1207 * Time output streamer.
1208 *
1209 * Generates output such as "396.0ns".
1210 *
1211 * For historical reasons Times are printed with the
1212 * following format flags (independent of the stream flags):
1213 * - `showpos`
1214 * - `fixed`
1215 * - `left`
1216 *
1217 * The stream `width` and `precision` are ignored; Time output always
1218 * includes ".0".
1219 *
1220 * \see As() for more flexible output formatting.
1221 *
1222 * \param [in,out] os The output stream.
1223 * \param [in] time The Time to put on the stream.
1224 * \return The stream.
1225 */
1226 std::ostream & operator << (std::ostream & os, const Time & time);
1227 /**
1228 * Time input streamer
1229 *
1230 * Uses the Time(const std::string &) constructor
1231 *
1232 * \param [in,out] is The input stream.
1233 * \param [out] time The Time variable to set from the stream data.
1234 * \return The stream.
1235 */
1236 std::istream & operator >> (std::istream & is, Time & time);
1237
1238
1239 /**
1240 * \ingroup time
1241 * \defgroup timecivil Standard Time Units.
1242 * Convenience constructors in standard units.
1243 *
1244 * For example:
1245 * \code
1246 * Time t = Seconds (2.0);
1247 * Simulator::Schedule (Seconds (5.0), ...);
1248 * \endcode
1249 */
1250 /**
1251 * \ingroup timecivil
1252 * Construct a Time in the indicated unit.
1253 * \param [in] value The value
1254 * \return The Time
1255 * @{
1256 */
Years(double value)1257 inline Time Years (double value)
1258 {
1259 return Time::FromDouble (value, Time::Y);
1260 }
Years(int64x64_t value)1261 inline Time Years (int64x64_t value)
1262 {
1263 return Time::From (value, Time::Y);
1264 }
Days(double value)1265 inline Time Days (double value)
1266 {
1267 return Time::FromDouble (value, Time::D);
1268 }
Days(int64x64_t value)1269 inline Time Days (int64x64_t value)
1270 {
1271 return Time::From (value, Time::D);
1272 }
Hours(double value)1273 inline Time Hours (double value)
1274 {
1275 return Time::FromDouble (value, Time::H);
1276 }
Hours(int64x64_t value)1277 inline Time Hours (int64x64_t value)
1278 {
1279 return Time::From (value, Time::H);
1280 }
Minutes(double value)1281 inline Time Minutes (double value)
1282 {
1283 return Time::FromDouble (value, Time::MIN);
1284 }
Minutes(int64x64_t value)1285 inline Time Minutes (int64x64_t value)
1286 {
1287 return Time::From (value, Time::MIN);
1288 }
Seconds(double value)1289 inline Time Seconds (double value)
1290 {
1291 return Time::FromDouble (value, Time::S);
1292 }
Seconds(int64x64_t value)1293 inline Time Seconds (int64x64_t value)
1294 {
1295 return Time::From (value, Time::S);
1296 }
MilliSeconds(uint64_t value)1297 inline Time MilliSeconds (uint64_t value)
1298 {
1299 return Time::FromInteger (value, Time::MS);
1300 }
MilliSeconds(int64x64_t value)1301 inline Time MilliSeconds (int64x64_t value)
1302 {
1303 return Time::From (value, Time::MS);
1304 }
MicroSeconds(uint64_t value)1305 inline Time MicroSeconds (uint64_t value)
1306 {
1307 return Time::FromInteger (value, Time::US);
1308 }
MicroSeconds(int64x64_t value)1309 inline Time MicroSeconds (int64x64_t value)
1310 {
1311 return Time::From (value, Time::US);
1312 }
NanoSeconds(uint64_t value)1313 inline Time NanoSeconds (uint64_t value)
1314 {
1315 return Time::FromInteger (value, Time::NS);
1316 }
NanoSeconds(int64x64_t value)1317 inline Time NanoSeconds (int64x64_t value)
1318 {
1319 return Time::From (value, Time::NS);
1320 }
PicoSeconds(uint64_t value)1321 inline Time PicoSeconds (uint64_t value)
1322 {
1323 return Time::FromInteger (value, Time::PS);
1324 }
PicoSeconds(int64x64_t value)1325 inline Time PicoSeconds (int64x64_t value)
1326 {
1327 return Time::From (value, Time::PS);
1328 }
FemtoSeconds(uint64_t value)1329 inline Time FemtoSeconds (uint64_t value)
1330 {
1331 return Time::FromInteger (value, Time::FS);
1332 }
FemtoSeconds(int64x64_t value)1333 inline Time FemtoSeconds (int64x64_t value)
1334 {
1335 return Time::From (value, Time::FS);
1336 }
1337 /**@}*/ // Construct a Time in the indicated unit.
1338
1339
1340 /**
1341 * Scheduler interface.
1342 *
1343 * \note This is internal to the Time implementation.
1344 * \param [in] ts The time value, in the current unit.
1345 * \return A Time.
1346 * \relates Time
1347 */
TimeStep(uint64_t ts)1348 inline Time TimeStep (uint64_t ts)
1349 {
1350 return Time (ts);
1351 }
1352
1353 ATTRIBUTE_VALUE_DEFINE (Time);
1354 ATTRIBUTE_ACCESSOR_DEFINE (Time);
1355
1356 /**
1357 * \ingroup attribute_time
1358 * Helper to make a Time checker with bounded range.
1359 * Both limits are inclusive
1360 *
1361 * \param [in] min Minimum allowed value.
1362 * \param [in] max Maximum allowed value.
1363 * \return The AttributeChecker
1364 */
1365 Ptr<const AttributeChecker> MakeTimeChecker (const Time min, const Time max);
1366
1367 /**
1368 * \ingroup attribute_time
1369 * Helper to make an unbounded Time checker.
1370 *
1371 * \return The AttributeChecker
1372 */
1373 inline
MakeTimeChecker(void)1374 Ptr<const AttributeChecker> MakeTimeChecker (void)
1375 {
1376 return MakeTimeChecker (Time::Min (), Time::Max ());
1377 }
1378
1379 /**
1380 * \ingroup attribute_time
1381 * Helper to make a Time checker with a lower bound.
1382 *
1383 * \param [in] min Minimum allowed value.
1384 * \return The AttributeChecker
1385 */
1386 inline
MakeTimeChecker(const Time min)1387 Ptr<const AttributeChecker> MakeTimeChecker (const Time min)
1388 {
1389 return MakeTimeChecker (min, Time::Max ());
1390 }
1391
1392 /**
1393 * \ingroup time
1394 * A Time with attached unit, to facilitate output in that unit.
1395 */
1396 class TimeWithUnit
1397 {
1398 public:
1399 /**
1400 * Attach a unit to a Time
1401 *
1402 * \param [in] time The time.
1403 * \param [in] unit The unit to use for output
1404 */
TimeWithUnit(const Time time,const Time::Unit unit)1405 TimeWithUnit (const Time time, const Time::Unit unit)
1406 : m_time (time),
1407 m_unit (unit)
1408 { }
1409
1410 private:
1411 Time m_time; //!< The time
1412 Time::Unit m_unit; //!< The unit to use in output
1413
1414 /**
1415 * Output streamer
1416 * \param [in,out] os The stream.
1417 * \param [in] timeU The Time with desired unit
1418 * \returns The stream.
1419 */
1420 friend std::ostream & operator << (std::ostream & os, const TimeWithUnit & timeU);
1421
1422 }; // class TimeWithUnit
1423
1424 } // namespace ns3
1425
1426 #endif /* TIME_H */
1427