View | Details | Raw Unified | Return to bug 954
Collapse All | Expand All

(-)a/doc/tutorial/source/conceptual-overview.rst (-1 / +16 lines)
 Lines 313-319    Link Here 
313
``Debugging`` book and then select the ``Logging`` page.
313
``Debugging`` book and then select the ``Logging`` page.
314
314
315
You should now be looking at the Doxygen documentation for the Logging module.
315
You should now be looking at the Doxygen documentation for the Logging module.
316
In the list of ``#define``'s at the top of the page you will see the entry
316
In the list of ``#define's at the top of the page you will see the entry
317
for ``NS_LOG_COMPONENT_DEFINE``.  Before jumping in, it would probably be 
317
for ``NS_LOG_COMPONENT_DEFINE``.  Before jumping in, it would probably be 
318
good to look for the "Detailed Description" of the logging module to get a 
318
good to look for the "Detailed Description" of the logging module to get a 
319
feel for the overall operation.  You can either scroll down or select the
319
feel for the overall operation.  You can either scroll down or select the
 Lines 340-345    Link Here 
340
the first function run.  There is nothing at all special here.  Your 
340
the first function run.  There is nothing at all special here.  Your 
341
|ns3| script is just a C++ program.
341
|ns3| script is just a C++ program.
342
342
343
The next line sets the time resolution to one nanosecond, which happens
344
to be the default value:
345
346
::
347
348
    Time::SetResolution (Time::NS);
349
350
The resolution is the smallest time value that can be represented (as well as
351
the smallest representable difference between two time values).
352
You can change the resolution exactly once.  The mechanism enabling this
353
flexibility is somewhat memory hungry, so once the resolution has been
354
set explicitly we release the memory, preventing further updates.   (If
355
you don't set the resolution explicitly, it will default to one nanosecond,
356
and the memory will be released when the simulation starts.)
357
343
The next two lines of the script are used to enable two logging components that
358
The next two lines of the script are used to enable two logging components that
344
are built into the Echo Client and Echo Server applications:
359
are built into the Echo Client and Echo Server applications:
345
360
(-)a/examples/tutorial/first.cc (+1 lines)
 Lines 27-32    Link Here 
27
int
27
int
28
main (int argc, char *argv[])
28
main (int argc, char *argv[])
29
{
29
{
30
  Time::SetResolution (Time::NS);
30
  LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
31
  LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
31
  LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
32
  LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
32
33
(-)a/src/core/model/nstime.h (-141 / +260 lines)
 Lines 26-150    Link Here 
26
#include "int64x64.h"
26
#include "int64x64.h"
27
#include <stdint.h>
27
#include <stdint.h>
28
#include <cmath>
28
#include <cmath>
29
#include <set>
29
#include <ostream>
30
#include <ostream>
30
31
31
namespace ns3 {
32
namespace ns3 {
32
33
34
// Forward declaration
35
class Simulator;
36
  
33
/**
37
/**
34
 * \ingroup core
38
 * \ingroup core
35
 * \defgroup time Time
39
 * \defgroup time Time
36
 */
40
 */
37
/**
41
/**
38
 * \ingroup time
42
 * \ingroup time
39
 * \brief keep track of time unit.
43
 * \brief Keep track of time values and allow control of global simulation resolution.
40
 *
44
 *
41
 * This template class is used to keep track of the value
45
 * This class defines the classic addition/subtraction C++ arithmetic
42
 * of a specific time unit: the type TimeUnit<1> is used to
46
 * operators +, -, +=, -=, and all the classic comparison operators:
43
 * keep track of seconds, the type TimeUnit<2> is used to keep
44
 * track of seconds squared, the type TimeUnit<-1> is used to
45
 * keep track of 1/seconds, etc.
46
 *
47
 * This base class defines all the functionality shared by all
48
 * these time unit objects: it defines all the classic arithmetic
49
 * operators +, -, *, /, and all the classic comparison operators:
50
 * ==, !=, <, >, <=, >=. It is thus easy to add, substract, or
47
 * ==, !=, <, >, <=, >=. It is thus easy to add, substract, or
51
 * multiply multiple TimeUnit objects. The return type of any such
48
 * compare Time objects.
52
 * arithmetic expression is always a TimeUnit object.
53
 *
54
 * The ns3::uint64_t, ns3::Time, ns3::TimeSquare, and ns3::TimeInvert classes
55
 * are aliases for the TimeUnit<0>, TimeUnit<1>, TimeUnit<2> and TimeUnit<-1>
56
 * types respectively.
57
 *
58
 * For example:
59
 * \code
60
 * Time<1> t1 = Seconds (10.0);
61
 * Time<1> t2 = Seconds (10.0);
62
 * Time<2> t3 = t1 * t2;
63
 * Time<0> t4 = t1 / t2;
64
 * Time<3> t5 = t3 * t1;
65
 * Time<-2> t6 = t1 / t5;
66
 * TimeSquare t7 = t3;
67
 * uint64_t s = t4;
68
 * \endcode
69
 *
70
 * If you try to assign the result of an expression which does not
71
 * match the type of the variable it is assigned to, you will get a
72
 * compiler error. For example, the following will not compile:
73
 * \code
74
 * Time<1> = Seconds (10.0) * Seconds (1.5);
75
 * \endcode
76
 *
77
 * You can also use the following non-member functions to manipulate
78
 * any of these ns3::TimeUnit object:
79
 *  - \ref ns3-Time-Abs ns3::Abs
80
 *  - \ref ns3-Time-Max ns3::Max
81
 *  - \ref ns3-Time-Min ns3::Min
82
 */
83
/**
84
 * \ingroup time
85
 * \brief keep track of time values and allow control of global simulation resolution
86
 *
87
 * This class defines all the classic C++ arithmetic
88
 * operators +, -, *, /, and all the classic comparison operators:
89
 * ==, !=, <, >, <=, >=. It is thus easy to add, substract, or
90
 * multiply multiple Time objects.
91
 *
92
 * The ns3::uint64_t, ns3::TimeSquare, and ns3::TimeInvert classes
93
 * are backward-compatibility aliases for ns3::Time.
94
 *
49
 *
95
 * For example:
50
 * For example:
96
 * \code
51
 * \code
97
 * Time t1 = Seconds (10.0);
52
 * Time t1 = Seconds (10.0);
98
 * Time t2 = Seconds (10.0);
53
 * Time t2 = Seconds (10.0);
99
 * Time t3 = t1 * t2;
54
 * Time t3 = t1;
100
 * Time t4 = t1 / t2;
55
 * t3 += t2;
101
 * Time t5 = t3 * t1;
102
 * Time t6 = t1 / t5;
103
 * Time t7 = t3;
104
 * \endcode
56
 * \endcode
105
 *
57
 *
106
 * You can also use the following non-member functions to manipulate
58
 * You can also use the following non-member functions to manipulate
107
 * any of these ns3::Time object:
59
 * any of these ns3::Time object:
108
 *  - \ref ns3-Time-Abs ns3::Abs
60
 *  - \ref Abs()
109
 *  - \ref ns3-Time-Max ns3::Max
61
 *  - \ref Max()
110
 *  - \ref ns3-Time-Min ns3::Min
62
 *  - \ref Min()
111
 *
63
 *
112
 * This class also controls
64
 * This class also controls the resolution of the underlying time value.
113
 * the resolution of the underlying time value . The default resolution
65
 * The resolution is the smallest representable time interval.
114
 * is nanoseconds. That is, TimeStep (1).GetNanoSeconds () will return
66
 * The default resolution is nanoseconds.  
115
 * 1. It is possible to either increase or decrease the resolution and the
116
 * code tries really hard to make this easy.
117
 *
67
 *
118
 * If your resolution is X (say, nanoseconds) and if you create Time objects 
68
 * To change the resolution, use SetResolution().  All Time objects created
119
 * with a lower resolution (say, picoseconds), don't expect that this 
69
 * before the call to SetResolution() will be updated to the new resolution.
120
 * code will return 1: PicoSeconds (1).GetPicoSeconds (). It will most 
70
 * This can only be done once!  (Tracking each Time object uses 4 pointers.
121
 * likely return 0 because the Time object has only 64 bits of fractional 
71
 * For speed, once we convert the existing instances we discard the recording
122
 * precision which means that PicoSeconds (1) is stored as a 64-bit aproximation
72
 * data structure and stop tracking new instances, so we have no way
123
 * of 1/1000 in the Time object. If you later multiply it again by the exact 
73
 * to do a second conversion.)
124
 * value 1000, the result is unlikely to be 1 exactly. It will be close to
125
 * 1 but not exactly 1.
126
 * 
127
 * In general, it is thus a really bad idea to try to use time objects of a
128
 * resolution higher than the global resolution controlled through 
129
 * Time::SetResolution. If you do need to use picoseconds, it's thus best
130
 * to switch the global resolution to picoseconds to avoid nasty surprises.
131
 *
74
 *
132
 * Another important issue to keep in mind is that if you increase the
75
 * Because of the memory (and modest construction cost) of tracking Time
133
 * global resolution, you also implicitely decrease the range of your simulation.
76
 * objects, simulations should explicitly choose a resolution before
134
 * i.e., the global simulation time is stored in a 64 bit integer whose interpretation
77
 * calling Simulator::Run ().  If you don't set the resolution explicitly,
135
 * will depend on the global resolution so, 2^64 picoseconds which is the maximum
78
 * it will default to one nanosecond, and the memory will be released
136
 * duration of your simulation if the global resolution is picoseconds 
79
 * when the simulation starts.
137
 * is smaller than 2^64 nanoseconds which is the maximum duration of your simulation
138
 * if the global resolution is nanoseconds.
139
 *
80
 *
140
 * Finally, don't even think about ever changing the global resolution after
81
 * If you increase the global resolution, you also implicitly decrease
141
 * creating Time objects: all Time objects created before the call to SetResolution
82
 * the range of your simulation.  The global simulation time is stored
142
 * will contain values which are not updated to the new resolution. In practice,
83
 * in a 64 bit integer, whose interpretation will depend on the global
143
 * the default value for the attributes of many models is indeed calculated
84
 * resolution.  Therefore the maximum duration of your simulation,
144
 * before the main function of the main program enters. Because of this, if you
85
 * if you use picoseconds, is 2^64 ps = 2^24 s = 7 months, whereas,
145
 * use one of these models (and it's likely), it's going to be hard to change
86
 * had you used nanoseconds, you could have run for 584 years.
146
 * the global simulation resolution in a way which gives reasonable results. This
147
 * issue has been filed as bug 954 in the ns-3 bugzilla installation.
148
 */
87
 */
149
class Time
88
class Time
150
{
89
{
 Lines 154-165    Link Here 
154
   */
93
   */
155
  enum Unit
94
  enum Unit
156
  {
95
  {
157
    S  = 0,
96
    S  = 0,   //!< second
158
    MS = 1,
97
    MS = 1,   //!< millisecond
159
    US = 2,
98
    US = 2,   //!< microsecond
160
    NS = 3,
99
    NS = 3,   //!< nanosecond
161
    PS = 4,
100
    PS = 4,   //!< picosecond
162
    FS = 5,
101
    FS = 5,   //!< femtosecond
163
    LAST = 6
102
    LAST = 6
164
  };
103
  };
165
104
 Lines 168-211    Link Here 
168
    m_data = o.m_data;
107
    m_data = o.m_data;
169
    return *this;
108
    return *this;
170
  }
109
  }
110
  inline Time &operator = (const int64_t &value)
111
  {
112
    m_data = value;
113
    return *this;
114
  }
171
  inline Time ()
115
  inline Time ()
172
    : m_data ()
116
    : m_data ()
173
  {}
117
  {
118
    if (g_markingTimes)
119
      {
120
	Mark (this);
121
      }
122
  }
174
  inline Time(const Time &o)
123
  inline Time(const Time &o)
175
    : m_data (o.m_data)
124
    : m_data (o.m_data)
176
  {}
125
  {
126
    if (g_markingTimes)
127
      {
128
	Mark (this);
129
      }
130
  }
177
  explicit inline Time (double v)
131
  explicit inline Time (double v)
178
    : m_data (lround (v))
132
    : m_data (lround (v))
179
  {}
133
  {
134
    if (g_markingTimes)
135
      {
136
	Mark (this);
137
      }
138
  }
180
  explicit inline Time (int v)
139
  explicit inline Time (int v)
181
    : m_data (v)
140
    : m_data (v)
182
  {}
141
  {
142
    if (g_markingTimes)
143
      {
144
	Mark (this);
145
      }
146
  }
183
  explicit inline Time (long int v)
147
  explicit inline Time (long int v)
184
    : m_data (v)
148
    : m_data (v)
185
  {}
149
  {
150
    if (g_markingTimes)
151
      {
152
	Mark (this);
153
      }
154
  }
186
  explicit inline Time (long long int v)
155
  explicit inline Time (long long int v)
187
    : m_data (v)
156
    : m_data (v)
188
  {}
157
  {
158
    if (g_markingTimes)
159
      {
160
	Mark (this);
161
      }
162
  }
189
  explicit inline Time (unsigned int v)
163
  explicit inline Time (unsigned int v)
190
    : m_data (v)
164
    : m_data (v)
191
  {}
165
  {
166
    if (g_markingTimes)
167
      {
168
	Mark (this);
169
      }
170
  }
192
  explicit inline Time (unsigned long int v)
171
  explicit inline Time (unsigned long int v)
193
    : m_data (v)
172
    : m_data (v)
194
  {}
173
  {
174
    if (g_markingTimes)
175
      {
176
	Mark (this);
177
      }
178
  }
195
  explicit inline Time (unsigned long long int v)
179
  explicit inline Time (unsigned long long int v)
196
    : m_data (v)
180
    : m_data (v)
197
  {}
181
  {
198
182
    if (g_markingTimes)
183
      {
184
	Mark (this);
185
      }
186
  }
199
  /**
187
  /**
200
   * \brief String constructor
188
   * \brief Construct Time object from common time expressions like "1ms"
201
   * Construct Time object from common time expressions like "
189
   *
202
   * 1ms" or "10s".  Supported units include:
190
   * Supported units include:
203
   * - s  (seconds)
191
   * - `s`  (seconds)
204
   * - ms (milliseconds)
192
   * - `ms` (milliseconds)
205
   * - us (microseconds)
193
   * - `us` (microseconds)
206
   * - ns (nanoseconds)
194
   * - `ns` (nanoseconds)
207
   * - ps (picoseconds)
195
   * - `ps` (picoseconds)
208
   * - fs (femtoseconds)
196
   * - `fs` (femtoseconds)
209
   *
197
   *
210
   * There can be no white space between the numerical portion
198
   * There can be no white space between the numerical portion
211
   * and the units.  Any otherwise malformed string causes a fatal error to
199
   * and the units.  Any otherwise malformed string causes a fatal error to
 Lines 215-220    Link Here 
215
  explicit Time (const std::string & s);
203
  explicit Time (const std::string & s);
216
204
217
  /**
205
  /**
206
   *  Destructor
207
   */
208
  ~Time ()
209
  {
210
    if (g_markingTimes)
211
      {
212
        Clear (this);
213
      }
214
  }
215
  
216
  /**
218
   * \return true if the time is zero, false otherwise.
217
   * \return true if the time is zero, false otherwise.
219
   */
218
   */
220
  inline bool IsZero (void) const
219
  inline bool IsZero (void) const
 Lines 249-255    Link Here 
249
  {
248
  {
250
    return m_data > 0;
249
    return m_data > 0;
251
  }
250
  }
252
251
  /**
252
   *  \return -1,0,+1 if `this < o`, `this == o`, or `this > o`
253
   */
253
  inline int Compare (const Time &o) const
254
  inline int Compare (const Time &o) const
254
  {
255
  {
255
    return (m_data < o.m_data) ? -1 : (m_data == o.m_data) ? 0 : 1;
256
    return (m_data < o.m_data) ? -1 : (m_data == o.m_data) ? 0 : 1;
 Lines 305-312    Link Here 
305
    return ToInteger (Time::FS);
306
    return ToInteger (Time::FS);
306
  }
307
  }
307
  /**
308
  /**
308
   * \returns an approximation of the time stored in this
309
   * \returns the raw time value, in the current units
309
   *          instance in the units specified in m_tsPrecision.
310
   */
310
   */
311
  inline int64_t GetTimeStep (void) const
311
  inline int64_t GetTimeStep (void) const
312
  {
312
  {
 Lines 436-465    Link Here 
436
  }
436
  }
437
  explicit inline Time (const int64x64_t &value)
437
  explicit inline Time (const int64x64_t &value)
438
    : m_data (value.GetHigh ())
438
    : m_data (value.GetHigh ())
439
  {}
439
  {
440
    if (g_markingTimes)
441
      {
442
	Mark (this);
443
      }
444
  }
440
  inline static Time From (const int64x64_t &value)
445
  inline static Time From (const int64x64_t &value)
441
  {
446
  {
442
    return Time (value);
447
    return Time (value);
443
  }
448
  }
444
449
445
private:
450
private:
451
  /**
452
   * How to convert between other units and the current unit
453
   */
446
  struct Information
454
  struct Information
447
  {
455
  {
448
    bool toMul;
456
    bool toMul;                     //!< Multiply when converting To, otherwise divide
449
    bool fromMul;
457
    bool fromMul;                   //!< Multiple when converting From, otherwise divide
450
    uint64_t factor;
458
    uint64_t factor;                //!< Ratio of this unit / current unit
451
    int64x64_t timeTo;
459
    int64x64_t timeTo;              //!< Multiplier to convert to this unit
452
    int64x64_t timeFrom;
460
    int64x64_t timeFrom;            //!< Multiplier to convert from this unit
453
  };
461
  };
462
  /**
463
   * Current time unit, and conversion info.
464
   */
454
  struct Resolution
465
  struct Resolution
455
  {
466
  {
456
    struct Information info[LAST];
467
    struct Information info[LAST];  //!<  Conversion info from current unit
457
    enum Time::Unit unit;
468
    enum Time::Unit unit;           //!<  Current time unit
458
  };
469
  };
459
470
460
  static inline struct Resolution *PeekResolution (void)
471
  static inline struct Resolution *PeekResolution (void)
461
  {
472
  {
462
    static struct Time::Resolution resolution = GetNsResolution ();
473
    static struct Time::Resolution resolution = SetDefaultNsResolution ();
463
    return &resolution;
474
    return &resolution;
464
  }
475
  }
465
  static inline struct Information *PeekInformation (enum Unit timeUnit)
476
  static inline struct Information *PeekInformation (enum Unit timeUnit)
 Lines 467-474    Link Here 
467
    return &(PeekResolution ()->info[timeUnit]);
478
    return &(PeekResolution ()->info[timeUnit]);
468
  }
479
  }
469
480
470
  static struct Resolution GetNsResolution (void);
481
  static struct Resolution SetDefaultNsResolution (void);
471
  static void SetResolution (enum Unit unit, struct Resolution *resolution);
482
  static void SetResolution (enum Unit unit, struct Resolution *resolution,
483
                             const bool convert = true);
484
485
  /**
486
   *  Record all instances of Time, so we can rescale them when
487
   *  the resolution changes.
488
   *
489
   *  \intern
490
   *
491
   *  We use a std::set so we can remove the record easily when
492
   *  ~Time() is called.
493
   *
494
   *  We don't use Ptr<Time>, because we would have to bloat every Time
495
   *  instance with SimpleRefCount<Time>.
496
   *
497
   *  Seems like this should be std::set< Time * const >, but
498
   *  [Stack Overflow](http://stackoverflow.com/questions/5526019/compile-errors-stdset-with-const-members)
499
   *  says otherwise, quoting the standard:
500
   *
501
   *  > &sect;23.1/3 states that std::set key types must be assignable
502
   *  > and copy constructable; clearly a const type will not be assignable.
503
   */
504
  typedef std::set< Time * > MarkedTimes;
505
  /**
506
   *  Record of outstanding Time objects which will need conversion
507
   *  when the resolution is set.
508
   *
509
   *  \intern
510
   *
511
   *  Use a classic static variable so we can check in Time ctors
512
   *  without a function call.  
513
   *
514
   *  We'd really like to initialize this here, but we don't want to require
515
   *  C++0x, so we init in time.cc.  To ensure that happens before first use,
516
   *  we add a call to StaticInit (below) to every compilation unit which
517
   *  includes nstime.h.
518
   */
519
  static MarkedTimes * g_markingTimes;
520
public:
521
  /**
522
   *  Function to force static initialization of Time
523
   */
524
  static bool StaticInit ();
525
private:
526
527
  friend class Simulator;
528
  /**
529
   *  Remove all MarkedTimes.
530
   *
531
   *  \intern
532
   *  Has to be visible to the Simulator class, hence the friending.
533
   */
534
  static void ClearMarkedTimes ();
535
  /**
536
   *  Record a Time instance with the MarkedTimes
537
   */
538
  static void Mark (Time * const time);
539
  /**
540
   *  Remove a Time instance from the MarkedTimes, called by ~Time()
541
   */
542
  static void Clear (Time * const time);
543
  /**
544
   *  Convert existing Times to the new unit.
545
   */
546
  static void ConvertTimes (const enum Unit unit);
472
547
473
  friend bool operator == (const Time &lhs, const Time &rhs);
548
  friend bool operator == (const Time &lhs, const Time &rhs);
474
  friend bool operator != (const Time &lhs, const Time &rhs);
549
  friend bool operator != (const Time &lhs, const Time &rhs);
 Lines 484-492    Link Here 
484
  friend Time Max (const Time &ta, const Time &tb);
559
  friend Time Max (const Time &ta, const Time &tb);
485
  friend Time Min (const Time &ta, const Time &tb);
560
  friend Time Min (const Time &ta, const Time &tb);
486
561
487
  int64_t m_data;
562
  
488
};
563
  int64_t m_data;                   //!< Virtual time value, in the current unit.
564
  
565
};  // class Time
566
  
489
567
568
// Force static initialization of Time
569
static bool g_TimeStaticInit = Time::StaticInit ();
570
  
490
inline bool
571
inline bool
491
operator == (const Time &lhs, const Time &rhs)
572
operator == (const Time &lhs, const Time &rhs)
492
{
573
{
 Lines 537-544    Link Here 
537
}
618
}
538
619
539
/**
620
/**
540
 * \anchor ns3-Time-Abs
621
 * Absolute value function for Time
541
 * \relates ns3::TimeUnit
622
 *
542
 * \param time the input value
623
 * \param time the input value
543
 * \returns the absolute value of the input value.
624
 * \returns the absolute value of the input value.
544
 */
625
 */
 Lines 547-554    Link Here 
547
  return Time ((time.m_data < 0) ? -time.m_data : time.m_data);
628
  return Time ((time.m_data < 0) ? -time.m_data : time.m_data);
548
}
629
}
549
/**
630
/**
550
 * \anchor ns3-Time-Max
551
 * \relates ns3::TimeUnit
552
 * \param ta the first value
631
 * \param ta the first value
553
 * \param tb the seconds value
632
 * \param tb the seconds value
554
 * \returns the max of the two input values.
633
 * \returns the max of the two input values.
 Lines 558-565    Link Here 
558
  return Time ((ta.m_data < tb.m_data) ? tb : ta);
637
  return Time ((ta.m_data < tb.m_data) ? tb : ta);
559
}
638
}
560
/**
639
/**
561
 * \anchor ns3-Time-Min
562
 * \relates ns3::TimeUnit
563
 * \param ta the first value
640
 * \param ta the first value
564
 * \param tb the seconds value
641
 * \param tb the seconds value
565
 * \returns the min of the two input values.
642
 * \returns the min of the two input values.
 Lines 570-576    Link Here 
570
}
647
}
571
648
572
649
650
/**
651
 * \brief Time output streamer.
652
 * 
653
 * Generates output such as "3.96ns"
654
 * \relates ns3::Time
655
 */
573
std::ostream& operator<< (std::ostream& os, const Time & time);
656
std::ostream& operator<< (std::ostream& os, const Time & time);
657
/**
658
 * \brief Time input streamer
659
 *
660
 * Uses the Time::Time (const std::string &) constructor
661
 * \relates ns3::Time
662
 */
574
std::istream& operator>> (std::istream& is, Time & time);
663
std::istream& operator>> (std::istream& is, Time & time);
575
664
576
/**
665
/**
 Lines 582-587    Link Here 
582
 * Simulator::Schedule (Seconds (5.0), ...);
671
 * Simulator::Schedule (Seconds (5.0), ...);
583
 * \endcode
672
 * \endcode
584
 * \param seconds seconds value
673
 * \param seconds seconds value
674
 * \relates ns3::Time
585
 */
675
 */
586
inline Time Seconds (double seconds)
676
inline Time Seconds (double seconds)
587
{
677
{
 Lines 597-602    Link Here 
597
 * Simulator::Schedule (MilliSeconds (5), ...);
687
 * Simulator::Schedule (MilliSeconds (5), ...);
598
 * \endcode
688
 * \endcode
599
 * \param ms milliseconds value
689
 * \param ms milliseconds value
690
 * \relates ns3::Time
600
 */
691
 */
601
inline Time MilliSeconds (uint64_t ms)
692
inline Time MilliSeconds (uint64_t ms)
602
{
693
{
 Lines 611-616    Link Here 
611
 * Simulator::Schedule (MicroSeconds (5), ...);
702
 * Simulator::Schedule (MicroSeconds (5), ...);
612
 * \endcode
703
 * \endcode
613
 * \param us microseconds value
704
 * \param us microseconds value
705
 * \relates ns3::Time
614
 */
706
 */
615
inline Time MicroSeconds (uint64_t us)
707
inline Time MicroSeconds (uint64_t us)
616
{
708
{
 Lines 625-630    Link Here 
625
 * Simulator::Schedule (NanoSeconds (5), ...);
717
 * Simulator::Schedule (NanoSeconds (5), ...);
626
 * \endcode
718
 * \endcode
627
 * \param ns nanoseconds value
719
 * \param ns nanoseconds value
720
 * \relates ns3::Time
628
 */
721
 */
629
inline Time NanoSeconds (uint64_t ns)
722
inline Time NanoSeconds (uint64_t ns)
630
{
723
{
 Lines 639-644    Link Here 
639
 * Simulator::Schedule (PicoSeconds (5), ...);
732
 * Simulator::Schedule (PicoSeconds (5), ...);
640
 * \endcode
733
 * \endcode
641
 * \param ps picoseconds value
734
 * \param ps picoseconds value
735
 * \relates ns3::Time
642
 */
736
 */
643
inline Time PicoSeconds (uint64_t ps)
737
inline Time PicoSeconds (uint64_t ps)
644
{
738
{
 Lines 653-658    Link Here 
653
 * Simulator::Schedule (FemtoSeconds (5), ...);
747
 * Simulator::Schedule (FemtoSeconds (5), ...);
654
 * \endcode
748
 * \endcode
655
 * \param fs femtoseconds value
749
 * \param fs femtoseconds value
750
 * \relates ns3::Time
656
 */
751
 */
657
inline Time FemtoSeconds (uint64_t fs)
752
inline Time FemtoSeconds (uint64_t fs)
658
{
753
{
 Lines 660-685    Link Here 
660
}
755
}
661
756
662
757
758
/**
759
 * \see Seconds(double)
760
 * \relates ns3::Time
761
 */ 
663
inline Time Seconds (int64x64_t seconds)
762
inline Time Seconds (int64x64_t seconds)
664
{
763
{
665
  return Time::From (seconds, Time::S);
764
  return Time::From (seconds, Time::S);
666
}
765
}
766
/**
767
 * \see MilliSeconds(uint64_t)
768
 * \relates ns3::Time
769
 */ 
667
inline Time MilliSeconds (int64x64_t ms)
770
inline Time MilliSeconds (int64x64_t ms)
668
{
771
{
669
  return Time::From (ms, Time::MS);
772
  return Time::From (ms, Time::MS);
670
}
773
}
774
/**
775
 * \see MicroSeconds(uint64_t)
776
 * \relates ns3::Time
777
 */ 
671
inline Time MicroSeconds (int64x64_t us)
778
inline Time MicroSeconds (int64x64_t us)
672
{
779
{
673
  return Time::From (us, Time::US);
780
  return Time::From (us, Time::US);
674
}
781
}
782
/**
783
 * \see NanoSeconds(uint64_t)
784
 * \relates ns3::Time
785
 */ 
675
inline Time NanoSeconds (int64x64_t ns)
786
inline Time NanoSeconds (int64x64_t ns)
676
{
787
{
677
  return Time::From (ns, Time::NS);
788
  return Time::From (ns, Time::NS);
678
}
789
}
790
/**
791
 * \see PicoSeconds(uint64_t)
792
 * \relates ns3::Time
793
 */ 
679
inline Time PicoSeconds (int64x64_t ps)
794
inline Time PicoSeconds (int64x64_t ps)
680
{
795
{
681
  return Time::From (ps, Time::PS);
796
  return Time::From (ps, Time::PS);
682
}
797
}
798
/**
799
 * \see FemtoSeconds(uint64_t)
800
 * \relates ns3::Time
801
 */ 
683
inline Time FemtoSeconds (int64x64_t fs)
802
inline Time FemtoSeconds (int64x64_t fs)
684
{
803
{
685
  return Time::From (fs, Time::FS);
804
  return Time::From (fs, Time::FS);
(-)a/src/core/model/simulator.cc (+1 lines)
 Lines 157-162    Link Here 
157
Simulator::Run (void)
157
Simulator::Run (void)
158
{
158
{
159
  NS_LOG_FUNCTION_NOARGS ();
159
  NS_LOG_FUNCTION_NOARGS ();
160
  Time::ClearMarkedTimes ();
160
  GetImpl ()->Run ();
161
  GetImpl ()->Run ();
161
}
162
}
162
163
(-)a/src/core/model/time.cc (-24 / +164 lines)
 Lines 27-39    Link Here 
27
#include "object.h"
27
#include "object.h"
28
#include "config.h"
28
#include "config.h"
29
#include "log.h"
29
#include "log.h"
30
#include "simulator.h"
30
#include <cmath>
31
#include <cmath>
31
#include <sstream>
32
#include <sstream>
32
33
34
NS_LOG_COMPONENT_DEFINE ("Time");
35
33
namespace ns3 {
36
namespace ns3 {
34
37
35
NS_LOG_COMPONENT_DEFINE ("Time");
38
// The set of marked times
39
// static
40
Time::MarkedTimes * Time::g_markingTimes;
36
41
42
// Function called to force static initialization  
43
// static
44
bool Time::StaticInit ()
45
{
46
  static bool firstTime = true;
47
48
  if (firstTime)
49
    {
50
      if (! g_markingTimes)
51
	{
52
	  g_markingTimes = new Time::MarkedTimes;
53
	}
54
      
55
      // Schedule the cleanup.
56
      // We'd really like:
57
      //   NS_LOG_LOGIC ("scheduling ClearMarkedTimes()");
58
      //   Simulator::Schedule ( Seconds (0), & ClearMarkedTimes);
59
      //   [or even better:  Simulator::AtStart ( & ClearMarkedTimes ); ]
60
      // But this triggers a static initialization order error,
61
      // since the Simulator static initialization may not have occurred.
62
      // Instead, we call ClearMarkedTimes directly from Simulator::Run ()
63
      firstTime = false;
64
    }
65
  
66
  return firstTime;
67
}
68
69
  
37
Time::Time (const std::string& s)
70
Time::Time (const std::string& s)
38
{
71
{
39
  NS_LOG_FUNCTION (this << &s);
72
  NS_LOG_FUNCTION (this << &s);
 Lines 48-109    Link Here 
48
      if (trailer == std::string ("s"))
81
      if (trailer == std::string ("s"))
49
        {
82
        {
50
          *this = Time::FromDouble (r, Time::S);
83
          *this = Time::FromDouble (r, Time::S);
51
          return;
52
        }
84
        }
53
      if (trailer == std::string ("ms"))
85
      else if (trailer == std::string ("ms"))
54
        {
86
        {
55
          *this = Time::FromDouble (r, Time::MS);
87
          *this = Time::FromDouble (r, Time::MS);
56
          return;
57
        }
88
        }
58
      if (trailer == std::string ("us"))
89
      else if (trailer == std::string ("us"))
59
        {
90
        {
60
          *this = Time::FromDouble (r, Time::US);
91
          *this = Time::FromDouble (r, Time::US);
61
          return;
62
        }
92
        }
63
      if (trailer == std::string ("ns"))
93
      else if (trailer == std::string ("ns"))
64
        {
94
        {
65
          *this = Time::FromDouble (r, Time::NS);
95
          *this = Time::FromDouble (r, Time::NS);
66
          return;
67
        }
96
        }
68
      if (trailer == std::string ("ps"))
97
      else if (trailer == std::string ("ps"))
69
        {
98
        {
70
          *this = Time::FromDouble (r, Time::PS);
99
          *this = Time::FromDouble (r, Time::PS);
71
          return;
72
        }
100
        }
73
      if (trailer == std::string ("fs"))
101
      else if (trailer == std::string ("fs"))
74
        {
102
        {
75
          *this = Time::FromDouble (r, Time::FS);
103
          *this = Time::FromDouble (r, Time::FS);
76
          return;
77
        }
104
        }
78
      NS_ABORT_MSG ("Can't Parse Time " << s);
105
      else
106
        {
107
          NS_ABORT_MSG ("Can't Parse Time " << s);
108
        }
79
    }
109
    }
80
  // else
110
  else
81
  // they didn't provide units, assume seconds
111
    {
82
  std::istringstream iss;
112
      // they didn't provide units, assume seconds
83
  iss.str (s);
113
      std::istringstream iss;
84
  double v;
114
      iss.str (s);
85
  iss >> v;
115
      double v;
86
  *this = Time::FromDouble (v, Time::S);
116
      iss >> v;
117
      *this = Time::FromDouble (v, Time::S);
118
    }
119
  
120
  if (g_markingTimes)
121
    {
122
      Mark (this);
123
    }
87
}
124
}
88
125
126
// static
89
struct Time::Resolution
127
struct Time::Resolution
90
Time::GetNsResolution (void)
128
Time::SetDefaultNsResolution (void)
91
{
129
{
92
  NS_LOG_FUNCTION_NOARGS ();
130
  NS_LOG_FUNCTION_NOARGS ();
93
  struct Resolution resolution;
131
  struct Resolution resolution;
94
  SetResolution (Time::NS, &resolution);
132
  SetResolution (Time::NS, &resolution, false);
95
  return resolution;
133
  return resolution;
96
}
134
}
135
136
// static
97
void 
137
void 
98
Time::SetResolution (enum Unit resolution)
138
Time::SetResolution (enum Unit resolution)
99
{
139
{
100
  NS_LOG_FUNCTION (resolution);
140
  NS_LOG_FUNCTION (resolution);
101
  SetResolution (resolution, PeekResolution ());
141
  SetResolution (resolution, PeekResolution ());
102
}
142
}
143
144
145
// static
103
void 
146
void 
104
Time::SetResolution (enum Unit unit, struct Resolution *resolution)
147
Time::SetResolution (enum Unit unit, struct Resolution *resolution,
148
                     const bool convert /* = true */)
105
{
149
{
106
  NS_LOG_FUNCTION (unit << resolution);
150
  NS_LOG_FUNCTION (resolution);
151
  if (convert)
152
    { // We have to convert old values
153
      ConvertTimes (unit);
154
    }
155
  
107
  int8_t power [LAST] = { 15, 12, 9, 6, 3, 0};
156
  int8_t power [LAST] = { 15, 12, 9, 6, 3, 0};
108
  for (int i = 0; i < Time::LAST; i++)
157
  for (int i = 0; i < Time::LAST; i++)
109
    {
158
    {
 Lines 136-141    Link Here 
136
    }
185
    }
137
  resolution->unit = unit;
186
  resolution->unit = unit;
138
}
187
}
188
189
190
// static
191
void
192
Time::ClearMarkedTimes ()
193
{
194
  NS_LOG_FUNCTION_NOARGS ();
195
  if (g_markingTimes)
196
    {
197
      NS_LOG_LOGIC ("clearing MarkedTimes");
198
      delete g_markingTimes;
199
      g_markingTimes = 0;
200
    }
201
}  // Time::ClearMarkedTimes
202
  
203
204
// static
205
void
206
Time::Mark (Time * const time)
207
{
208
  NS_LOG_FUNCTION (time);
209
  NS_ASSERT (time != 0);
210
211
  if (g_markingTimes)
212
    {
213
      std::pair< MarkedTimes::iterator, bool> ret;
214
215
      ret = g_markingTimes->insert ( time);
216
      NS_LOG_LOGIC ("\t[" << g_markingTimes->size () << "] recording " << time);
217
  
218
      if (ret.second == false)
219
        {
220
          NS_LOG_WARN ("already recorded " << time << "!");
221
        }
222
   }
223
}  // Time::Mark ()
224
225
226
// static
227
void
228
Time::Clear (Time * const time)
229
{
230
  NS_LOG_FUNCTION (time);
231
  NS_ASSERT (time != 0);
232
  
233
  if (g_markingTimes)
234
    {
235
      NS_ASSERT_MSG (g_markingTimes->count (time) == 1,
236
		     "Time object " << time <<
237
		     " registered " << g_markingTimes->count (time) <<
238
		     " times (should be 1)." );
239
240
      MarkedTimes::size_type num = g_markingTimes->erase (time);
241
      if (num != 1)
242
	{
243
	  NS_LOG_WARN ("unexpected result erasing " << time << "!");
244
	  NS_LOG_WARN ("got " << num << ", expected 1");
245
	}
246
      else
247
	{
248
	  NS_LOG_LOGIC ("\t[" << g_markingTimes->size () << "] removing  " << time);
249
	}
250
    }
251
}  // Time::Clear ()
252
253
254
// static
255
void
256
Time::ConvertTimes (const enum Unit unit)
257
{
258
  NS_LOG_FUNCTION_NOARGS();
259
260
  NS_ASSERT_MSG (g_markingTimes != 0,
261
		 "No MarkedTimes registry. "
262
		 "Time::SetResolution () called more than once?");
263
  
264
  for ( MarkedTimes::iterator it = g_markingTimes->begin();
265
	it != g_markingTimes->end();
266
	it++ )
267
    {
268
      Time * const tp = *it;
269
      (*tp) = tp->ToInteger (unit);
270
    }
271
  
272
  NS_LOG_LOGIC ("logged " << g_markingTimes->size () << " Time objects.");
273
  
274
  ClearMarkedTimes ();
275
}  // Time::ConvertTimes ()
276
 
277
278
// static
139
enum Time::Unit
279
enum Time::Unit
140
Time::GetResolution (void)
280
Time::GetResolution (void)
141
{
281
{
(-)a/src/core/test/time-test-suite.cc (-10 / +11 lines)
 Lines 27-57    Link Here 
27
class TimeSimpleTestCase : public TestCase
27
class TimeSimpleTestCase : public TestCase
28
{
28
{
29
public:
29
public:
30
  TimeSimpleTestCase (enum Time::Unit resolution);
30
  TimeSimpleTestCase ();
31
private:
31
private:
32
  virtual void DoSetup (void);
32
  virtual void DoSetup (void);
33
  virtual void DoRun (void);
33
  virtual void DoRun (void);
34
  virtual void DoTeardown (void);
34
  virtual void DoTeardown (void);
35
  enum Time::Unit m_originalResolution;
36
  enum Time::Unit m_resolution;
37
};
35
};
38
36
39
TimeSimpleTestCase::TimeSimpleTestCase (enum Time::Unit resolution)
37
TimeSimpleTestCase::TimeSimpleTestCase ()
40
  : TestCase ("Sanity check of common time operations"),
38
  : TestCase ("Sanity check of common time operations")
41
    m_resolution (resolution)
42
{
39
{
43
}
40
}
44
41
45
void
42
void
46
TimeSimpleTestCase::DoSetup (void)
43
TimeSimpleTestCase::DoSetup (void)
47
{
44
{
48
  m_originalResolution = Time::GetResolution ();
49
}
45
}
50
46
51
void
47
void
52
TimeSimpleTestCase::DoRun (void)
48
TimeSimpleTestCase::DoRun (void)
53
{
49
{
54
  Time::SetResolution (m_resolution);
55
  NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (1.0).GetSeconds (), 1.0, TimeStep (1).GetSeconds (), 
50
  NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (1.0).GetSeconds (), 1.0, TimeStep (1).GetSeconds (), 
56
                             "is 1 really 1 ?");
51
                             "is 1 really 1 ?");
57
  NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (10.0).GetSeconds (), 10.0, TimeStep (1).GetSeconds (), 
52
  NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (10.0).GetSeconds (), 10.0, TimeStep (1).GetSeconds (), 
 Lines 70-81    Link Here 
70
  NS_TEST_ASSERT_MSG_EQ (FemtoSeconds (1).GetFemtoSeconds (), 1, 
65
  NS_TEST_ASSERT_MSG_EQ (FemtoSeconds (1).GetFemtoSeconds (), 1, 
71
                         "is 1fs really 1fs ?");
66
                         "is 1fs really 1fs ?");
72
#endif
67
#endif
68
69
  Time ten = NanoSeconds (10);
70
  int64_t tenValue = ten.GetInteger ();
71
  Time::SetResolution (Time::PS);
72
  int64_t tenKValue = ten.GetInteger ();
73
  NS_TEST_ASSERT_MSG_EQ (tenValue * 1000, tenKValue,
74
                         "change resolution to PS");
73
}
75
}
74
76
75
void 
77
void 
76
TimeSimpleTestCase::DoTeardown (void)
78
TimeSimpleTestCase::DoTeardown (void)
77
{
79
{
78
  Time::SetResolution (m_originalResolution);
79
}
80
}
80
81
81
class TimesWithSignsTestCase : public TestCase
82
class TimesWithSignsTestCase : public TestCase
 Lines 139-145    Link Here 
139
  TimeTestSuite ()
140
  TimeTestSuite ()
140
    : TestSuite ("time", UNIT)
141
    : TestSuite ("time", UNIT)
141
  {
142
  {
142
    AddTestCase (new TimeSimpleTestCase (Time::US), TestCase::QUICK);
143
    AddTestCase (new TimeSimpleTestCase (), TestCase::QUICK);
143
    AddTestCase (new TimesWithSignsTestCase (), TestCase::QUICK);
144
    AddTestCase (new TimesWithSignsTestCase (), TestCase::QUICK);
144
  }
145
  }
145
} g_timeTestSuite;
146
} g_timeTestSuite;

Return to bug 954