bug 954: back out changesets 1a2abe07b53d, 8934b7c0c1cb, and 8ef8d8bae350
authorTom Henderson <tomh@tomh.org>
Sat, 15 Dec 2012 23:02:03 -0800
changeset 9195 f0be2daaa38f
parent 9194 a420dcf7dceb
child 9196 097915486ed0
bug 954: back out changesets 1a2abe07b53d, 8934b7c0c1cb, and 8ef8d8bae350
doc/tutorial/source/conceptual-overview.rst
examples/tutorial/first.cc
src/core/bindings/callbacks_list.py
src/core/bindings/modulegen__gcc_ILP32.py
src/core/bindings/modulegen__gcc_LP64.py
src/core/model/nstime.h
src/core/model/simulator.cc
src/core/model/time.cc
src/core/test/time-test-suite.cc
--- a/doc/tutorial/source/conceptual-overview.rst	Sat Dec 15 11:32:58 2012 -0800
+++ b/doc/tutorial/source/conceptual-overview.rst	Sat Dec 15 23:02:03 2012 -0800
@@ -340,20 +340,6 @@
 the first function run.  There is nothing at all special here.  Your 
 |ns3| script is just a C++ program.
 
-The next line sets the time resolution to one nanosecond, which happens
-to be the default value:
-
-::
-
-    Time::SetResolution (Time::NS);
-
-You can change the resolution exactly once (which must be before
-``Simulator::Run ()`` is called, below).  The mechanism enabling this
-flexibility is somewhat memory hungry, so once the resolution has been
-set explicitly we release the memory, preventing further updates.  (If
-you don't set the resolution explicitly, it will default to one nanosecond,
-and the memory will be released when the simulation starts.)
-
 The next two lines of the script are used to enable two logging components that
 are built into the Echo Client and Echo Server applications:
 
--- a/examples/tutorial/first.cc	Sat Dec 15 11:32:58 2012 -0800
+++ b/examples/tutorial/first.cc	Sat Dec 15 23:02:03 2012 -0800
@@ -27,7 +27,6 @@
 int
 main (int argc, char *argv[])
 {
-  Time::SetResolution (Time::NS);
   LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
   LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
 
--- a/src/core/bindings/callbacks_list.py	Sat Dec 15 11:32:58 2012 -0800
+++ b/src/core/bindings/callbacks_list.py	Sat Dec 15 23:02:03 2012 -0800
@@ -1,5 +1,5 @@
 callback_classes = [
-    ['void', 'unsigned char*', 'long', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
+    ['void', 'unsigned char*', 'int', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
     ['void', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
     ['bool', 'std::string', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
 ]
--- a/src/core/bindings/modulegen__gcc_ILP32.py	Sat Dec 15 11:32:58 2012 -0800
+++ b/src/core/bindings/modulegen__gcc_ILP32.py	Sat Dec 15 23:02:03 2012 -0800
@@ -310,10 +310,6 @@
     module.add_class('Vector3DChecker', parent=root_module['ns3::AttributeChecker'])
     ## vector.h (module 'core'): ns3::Vector3DValue [class]
     module.add_class('Vector3DValue', parent=root_module['ns3::AttributeValue'])
-    typehandlers.add_type_alias('ns3::Vector3D', 'ns3::Vector')
-    typehandlers.add_type_alias('ns3::Vector3D*', 'ns3::Vector*')
-    typehandlers.add_type_alias('ns3::Vector3D&', 'ns3::Vector&')
-    module.add_typedef(root_module['ns3::Vector3D'], 'Vector')
     typehandlers.add_type_alias('ns3::ObjectPtrContainerValue', 'ns3::ObjectVectorValue')
     typehandlers.add_type_alias('ns3::ObjectPtrContainerValue*', 'ns3::ObjectVectorValue*')
     typehandlers.add_type_alias('ns3::ObjectPtrContainerValue&', 'ns3::ObjectVectorValue&')
@@ -328,6 +324,10 @@
     typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *', 'ns3::LogNodePrinter')
     typehandlers.add_type_alias('void ( * ) ( std::ostream & ) **', 'ns3::LogNodePrinter*')
     typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *&', 'ns3::LogNodePrinter&')
+    typehandlers.add_type_alias('ns3::Vector3D', 'ns3::Vector')
+    typehandlers.add_type_alias('ns3::Vector3D*', 'ns3::Vector*')
+    typehandlers.add_type_alias('ns3::Vector3D&', 'ns3::Vector&')
+    module.add_typedef(root_module['ns3::Vector3D'], 'Vector')
     typehandlers.add_type_alias('ns3::Vector3DValue', 'ns3::VectorValue')
     typehandlers.add_type_alias('ns3::Vector3DValue*', 'ns3::VectorValue*')
     typehandlers.add_type_alias('ns3::Vector3DValue&', 'ns3::VectorValue&')
@@ -2382,11 +2382,6 @@
                    'int', 
                    [param('ns3::Time const &', 'o')], 
                    is_const=True)
-    ## nstime.h (module 'core'): static void ns3::Time::FreezeResolution() [member function]
-    cls.add_method('FreezeResolution', 
-                   'void', 
-                   [], 
-                   is_static=True)
     ## nstime.h (module 'core'): static ns3::Time ns3::Time::From(ns3::int64x64_t const & from, ns3::Time::Unit timeUnit) [member function]
     cls.add_method('From', 
                    'ns3::Time', 
--- a/src/core/bindings/modulegen__gcc_LP64.py	Sat Dec 15 11:32:58 2012 -0800
+++ b/src/core/bindings/modulegen__gcc_LP64.py	Sat Dec 15 23:02:03 2012 -0800
@@ -310,10 +310,6 @@
     module.add_class('Vector3DChecker', parent=root_module['ns3::AttributeChecker'])
     ## vector.h (module 'core'): ns3::Vector3DValue [class]
     module.add_class('Vector3DValue', parent=root_module['ns3::AttributeValue'])
-    typehandlers.add_type_alias('ns3::Vector3D', 'ns3::Vector')
-    typehandlers.add_type_alias('ns3::Vector3D*', 'ns3::Vector*')
-    typehandlers.add_type_alias('ns3::Vector3D&', 'ns3::Vector&')
-    module.add_typedef(root_module['ns3::Vector3D'], 'Vector')
     typehandlers.add_type_alias('ns3::ObjectPtrContainerValue', 'ns3::ObjectVectorValue')
     typehandlers.add_type_alias('ns3::ObjectPtrContainerValue*', 'ns3::ObjectVectorValue*')
     typehandlers.add_type_alias('ns3::ObjectPtrContainerValue&', 'ns3::ObjectVectorValue&')
@@ -328,6 +324,10 @@
     typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *', 'ns3::LogNodePrinter')
     typehandlers.add_type_alias('void ( * ) ( std::ostream & ) **', 'ns3::LogNodePrinter*')
     typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *&', 'ns3::LogNodePrinter&')
+    typehandlers.add_type_alias('ns3::Vector3D', 'ns3::Vector')
+    typehandlers.add_type_alias('ns3::Vector3D*', 'ns3::Vector*')
+    typehandlers.add_type_alias('ns3::Vector3D&', 'ns3::Vector&')
+    module.add_typedef(root_module['ns3::Vector3D'], 'Vector')
     typehandlers.add_type_alias('ns3::Vector3DValue', 'ns3::VectorValue')
     typehandlers.add_type_alias('ns3::Vector3DValue*', 'ns3::VectorValue*')
     typehandlers.add_type_alias('ns3::Vector3DValue&', 'ns3::VectorValue&')
@@ -2382,11 +2382,6 @@
                    'int', 
                    [param('ns3::Time const &', 'o')], 
                    is_const=True)
-    ## nstime.h (module 'core'): static void ns3::Time::FreezeResolution() [member function]
-    cls.add_method('FreezeResolution', 
-                   'void', 
-                   [], 
-                   is_static=True)
     ## nstime.h (module 'core'): static ns3::Time ns3::Time::From(ns3::int64x64_t const & from, ns3::Time::Unit timeUnit) [member function]
     cls.add_method('From', 
                    'ns3::Time', 
--- a/src/core/model/nstime.h	Sat Dec 15 11:32:58 2012 -0800
+++ b/src/core/model/nstime.h	Sat Dec 15 23:02:03 2012 -0800
@@ -26,7 +26,6 @@
 #include "int64x64.h"
 #include <stdint.h>
 #include <cmath>
-#include <set>
 #include <ostream>
 
 namespace ns3 {
@@ -37,48 +36,115 @@
  */
 /**
  * \ingroup time
- * \brief Keep track of time values and allow control of global simulation resolution.
+ * \brief keep track of time unit.
+ *
+ * This template class is used to keep track of the value
+ * of a specific time unit: the type TimeUnit<1> is used to
+ * keep track of seconds, the type TimeUnit<2> is used to keep
+ * track of seconds squared, the type TimeUnit<-1> is used to
+ * keep track of 1/seconds, etc.
+ *
+ * This base class defines all the functionality shared by all
+ * these time unit objects: it defines all the classic arithmetic
+ * operators +, -, *, /, and all the classic comparison operators:
+ * ==, !=, <, >, <=, >=. It is thus easy to add, substract, or
+ * multiply multiple TimeUnit objects. The return type of any such
+ * arithmetic expression is always a TimeUnit object.
+ *
+ * The ns3::uint64_t, ns3::Time, ns3::TimeSquare, and ns3::TimeInvert classes
+ * are aliases for the TimeUnit<0>, TimeUnit<1>, TimeUnit<2> and TimeUnit<-1>
+ * types respectively.
  *
- * This class defines the classic addition/subtraction C++ arithmetic
- * operators +, -, +=, -=, and all the classic comparison operators:
+ * For example:
+ * \code
+ * Time<1> t1 = Seconds (10.0);
+ * Time<1> t2 = Seconds (10.0);
+ * Time<2> t3 = t1 * t2;
+ * Time<0> t4 = t1 / t2;
+ * Time<3> t5 = t3 * t1;
+ * Time<-2> t6 = t1 / t5;
+ * TimeSquare t7 = t3;
+ * uint64_t s = t4;
+ * \endcode
+ *
+ * If you try to assign the result of an expression which does not
+ * match the type of the variable it is assigned to, you will get a
+ * compiler error. For example, the following will not compile:
+ * \code
+ * Time<1> = Seconds (10.0) * Seconds (1.5);
+ * \endcode
+ *
+ * You can also use the following non-member functions to manipulate
+ * any of these ns3::TimeUnit object:
+ *  - \ref ns3-Time-Abs ns3::Abs
+ *  - \ref ns3-Time-Max ns3::Max
+ *  - \ref ns3-Time-Min ns3::Min
+ */
+/**
+ * \ingroup time
+ * \brief keep track of time values and allow control of global simulation resolution
+ *
+ * This class defines all the classic C++ arithmetic
+ * operators +, -, *, /, and all the classic comparison operators:
  * ==, !=, <, >, <=, >=. It is thus easy to add, substract, or
- * compare Time objects.
+ * multiply multiple Time objects.
+ *
+ * The ns3::uint64_t, ns3::TimeSquare, and ns3::TimeInvert classes
+ * are backward-compatibility aliases for ns3::Time.
  *
  * For example:
  * \code
  * Time t1 = Seconds (10.0);
  * Time t2 = Seconds (10.0);
- * Time t3 = t1;
- * t3 += t2;
+ * Time t3 = t1 * t2;
+ * Time t4 = t1 / t2;
+ * Time t5 = t3 * t1;
+ * Time t6 = t1 / t5;
+ * Time t7 = t3;
  * \endcode
  *
  * You can also use the following non-member functions to manipulate
  * any of these ns3::Time object:
- *  - \ref Abs()
- *  - \ref Max()
- *  - \ref Min()
+ *  - \ref ns3-Time-Abs ns3::Abs
+ *  - \ref ns3-Time-Max ns3::Max
+ *  - \ref ns3-Time-Min ns3::Min
  *
- * This class also controls the resolution of the underlying time value.
- * The resolution is the smallest representable time interval.
- * The default resolution is nanoseconds.  
+ * This class also controls
+ * the resolution of the underlying time value . The default resolution
+ * is nanoseconds. That is, TimeStep (1).GetNanoSeconds () will return
+ * 1. It is possible to either increase or decrease the resolution and the
+ * code tries really hard to make this easy.
  *
- * To change the resolution, use SetResolution().  All Time objects created
- * before the call to SetResolution() will be updated to the new resolution.
- * This can only be done once!  (Tracking each Time object uses 4 pointers.
- * For speed, once we convert the existing instances we discard the recording
- * data structure and stop tracking new instances, so we have no way
- * to do a second conversion.)
+ * If your resolution is X (say, nanoseconds) and if you create Time objects 
+ * with a lower resolution (say, picoseconds), don't expect that this 
+ * code will return 1: PicoSeconds (1).GetPicoSeconds (). It will most 
+ * likely return 0 because the Time object has only 64 bits of fractional 
+ * precision which means that PicoSeconds (1) is stored as a 64-bit aproximation
+ * of 1/1000 in the Time object. If you later multiply it again by the exact 
+ * value 1000, the result is unlikely to be 1 exactly. It will be close to
+ * 1 but not exactly 1.
+ * 
+ * In general, it is thus a really bad idea to try to use time objects of a
+ * resolution higher than the global resolution controlled through 
+ * Time::SetResolution. If you do need to use picoseconds, it's thus best
+ * to switch the global resolution to picoseconds to avoid nasty surprises.
  *
- * Because of the memory (and modest construction cost) of tracking Time
- * objects, simulations should explicitly choose a resolution before
- * calling Simulator::Run ().
+ * Another important issue to keep in mind is that if you increase the
+ * global resolution, you also implicitely decrease the range of your simulation.
+ * i.e., the global simulation time is stored in a 64 bit integer whose interpretation
+ * will depend on the global resolution so, 2^64 picoseconds which is the maximum
+ * duration of your simulation if the global resolution is picoseconds 
+ * is smaller than 2^64 nanoseconds which is the maximum duration of your simulation
+ * if the global resolution is nanoseconds.
  *
- * If you increase the global resolution, you also implicitly decrease
- * the range of your simulation.  The global simulation time is stored
- * in a 64 bit integer, whose interpretation will depend on the global
- * resolution.  Therefore the maximum duration of your simulation,
- * if you use picoseconds, is 2^64 ps = 2^24 s = 7 months, whereas,
- * had you used nanoseconds, you could have run for 584 years.
+ * Finally, don't even think about ever changing the global resolution after
+ * creating Time objects: all Time objects created before the call to SetResolution
+ * will contain values which are not updated to the new resolution. In practice,
+ * the default value for the attributes of many models is indeed calculated
+ * before the main function of the main program enters. Because of this, if you
+ * use one of these models (and it's likely), it's going to be hard to change
+ * the global simulation resolution in a way which gives reasonable results. This
+ * issue has been filed as bug 954 in the ns-3 bugzilla installation.
  */
 class Time
 {
@@ -88,12 +154,12 @@
    */
   enum Unit
   {
-    S  = 0,   //!< second
-    MS = 1,   //!< millisecond
-    US = 2,   //!< microsecond
-    NS = 3,   //!< nanosecond
-    PS = 4,   //!< picosecond
-    FS = 5,   //!< femtosecond
+    S  = 0,
+    MS = 1,
+    US = 2,
+    NS = 3,
+    PS = 4,
+    FS = 5,
     LAST = 6
   };
 
@@ -102,66 +168,44 @@
     m_data = o.m_data;
     return *this;
   }
-  inline Time &operator = (const int64_t &value)
-  {
-    m_data = value;
-    return *this;
-  }
   inline Time ()
     : m_data ()
-  {
-    Time::Track (this);
-  }
+  {}
   inline Time(const Time &o)
     : m_data (o.m_data)
-  {
-    Time::Track (this);
-  }
+  {}
   explicit inline Time (double v)
     : m_data (lround (v))
-  {
-    Time::Track (this);
-  }
+  {}
   explicit inline Time (int v)
     : m_data (v)
-  {
-    Time::Track (this);
-  }
+  {}
   explicit inline Time (long int v)
     : m_data (v)
-  {
-    Time::Track (this);
-  }
+  {}
   explicit inline Time (long long int v)
     : m_data (v)
-  {
-    Time::Track (this);
-  }
+  {}
   explicit inline Time (unsigned int v)
     : m_data (v)
-  {
-    Time::Track (this);
-  }
+  {}
   explicit inline Time (unsigned long int v)
     : m_data (v)
-  {
-    Time::Track (this);
-  }
+  {}
   explicit inline Time (unsigned long long int v)
     : m_data (v)
-  {
-    Time::Track (this);
-  }
+  {}
+
   /**
-   * \brief Construct Time object from common time expressions like "1ms"
-   *
-   * Supported units include:
-   * - `s`  (seconds)
-   * - `ms` (milliseconds)
-   * - `us` (microseconds)
-   * - `ns` (nanoseconds)
-   * - `ps` (picoseconds)
-   * - `fs` (femtoseconds)
+   * \brief String constructor
+   * Construct Time object from common time expressions like "
+   * 1ms" or "10s".  Supported units include:
+   * - s  (seconds)
+   * - ms (milliseconds)
+   * - us (microseconds)
+   * - ns (nanoseconds)
+   * - ps (picoseconds)
+   * - fs (femtoseconds)
    *
    * There can be no white space between the numerical portion
    * and the units.  Any otherwise malformed string causes a fatal error to
@@ -171,14 +215,6 @@
   explicit Time (const std::string & s);
 
   /**
-   *  Destructor
-   */
-  ~Time ()
-  {
-    Time::UnTrack (this);
-  }
-  
-  /**
    * \return true if the time is zero, false otherwise.
    */
   inline bool IsZero (void) const
@@ -213,9 +249,7 @@
   {
     return m_data > 0;
   }
-  /**
-   *  \return -1,0,+1 if `this < o`, `this == o`, or `this > o`
-   */
+
   inline int Compare (const Time &o) const
   {
     return (m_data < o.m_data) ? -1 : (m_data == o.m_data) ? 0 : 1;
@@ -271,7 +305,8 @@
     return ToInteger (Time::FS);
   }
   /**
-   * \returns the raw time value, in the current units
+   * \returns an approximation of the time stored in this
+   *          instance in the units specified in m_tsPrecision.
    */
   inline int64_t GetTimeStep (void) const
   {
@@ -293,19 +328,9 @@
    * Change the global resolution used to convert all 
    * user-provided time values in Time objects and Time objects
    * in user-expected time units.
-   *
-   * This function can be called only once. Further calls
-   * will trigger a forced crash.
    */
   static void SetResolution (enum Unit resolution);
   /**
-   * Freeze the current time resolution. This function is called
-   * internally from the Simulator::Run function. After this
-   * function is called, calls to SetResolution will trigger
-   * an assert.
-   */
-  static void FreezeResolution(void);
-  /**
    * \returns the current global resolution.
    */
   static enum Unit GetResolution (void);
@@ -411,38 +436,30 @@
   }
   explicit inline Time (const int64x64_t &value)
     : m_data (value.GetHigh ())
-  {
-    Time::Track (this);
-  }
+  {}
   inline static Time From (const int64x64_t &value)
   {
     return Time (value);
   }
 
 private:
-  /**
-   * How to convert between other units and the current unit
-   */
   struct Information
   {
-    bool toMul;                     //!< Multiply when converting To, otherwise divide
-    bool fromMul;                   //!< Multiple when converting From, otherwise divide
-    uint64_t factor;                //!< Ratio of this unit / current unit
-    int64x64_t timeTo;              //!< Multiplier to convert to this unit
-    int64x64_t timeFrom;            //!< Multiplier to convert from this unit
+    bool toMul;
+    bool fromMul;
+    uint64_t factor;
+    int64x64_t timeTo;
+    int64x64_t timeFrom;
   };
-  /**
-   * Current time unit, and conversion info.
-   */
   struct Resolution
   {
-    struct Information info[LAST];  //!<  Conversion info from current unit
-    enum Time::Unit unit;           //!<  Current time unit
+    struct Information info[LAST];
+    enum Time::Unit unit;
   };
 
   static inline struct Resolution *PeekResolution (void)
   {
-    static struct Time::Resolution resolution = SetDefaultNsResolution ();
+    static struct Time::Resolution resolution = GetNsResolution ();
     return &resolution;
   }
   static inline struct Information *PeekInformation (enum Unit timeUnit)
@@ -450,40 +467,8 @@
     return &(PeekResolution ()->info[timeUnit]);
   }
 
-  static struct Resolution SetDefaultNsResolution (void);
+  static struct Resolution GetNsResolution (void);
   static void SetResolution (enum Unit unit, struct Resolution *resolution);
-  static void DoSetResolution (enum Unit unit, struct Resolution *resolution);
-  static void FreezeResolution(enum Unit unit);
-
-  /**
-   * Record all instances of Time, so we can rescale them when
-   * the resolution changes.
-   *
-   * \internal
-   *
-   * We use a std::set so we can remove the record easily when
-   * ~Time() is called.
-   *
-   * We don't use Ptr<Time>, because we would have to bloat every Time
-   * instance with SimpleRefCount<Time>.
-   *
-   * Seems like this should be std::set< Time * const >, but
-   * http://stackoverflow.com/questions/5526019/compile-errors-stdset-with-const-members
-   * (and gcc 4.2) say no.
-   */
-  typedef std::set< Time * > TimesSet;
-  static TimesSet * GetTimesSet ();
-  static TimesSet ** PeekTimesSet ();
-  /**
-   * Start tracking a Time instance with the TimesSet
-   * to be able to change the underlying value if the
-   * time resolution changes later
-   */
-  static void Track (Time * const time);
-  /**
-   * We do not need to track a Time instance anymore
-   */
-  static void UnTrack (Time * const time);
 
   friend bool operator == (const Time &lhs, const Time &rhs);
   friend bool operator != (const Time &lhs, const Time &rhs);
@@ -552,8 +537,8 @@
 }
 
 /**
- * Absolute value function for Time
- *
+ * \anchor ns3-Time-Abs
+ * \relates ns3::TimeUnit
  * \param time the input value
  * \returns the absolute value of the input value.
  */
@@ -562,6 +547,8 @@
   return Time ((time.m_data < 0) ? -time.m_data : time.m_data);
 }
 /**
+ * \anchor ns3-Time-Max
+ * \relates ns3::TimeUnit
  * \param ta the first value
  * \param tb the seconds value
  * \returns the max of the two input values.
@@ -571,6 +558,8 @@
   return Time ((ta.m_data < tb.m_data) ? tb : ta);
 }
 /**
+ * \anchor ns3-Time-Min
+ * \relates ns3::TimeUnit
  * \param ta the first value
  * \param tb the seconds value
  * \returns the min of the two input values.
@@ -581,19 +570,7 @@
 }
 
 
-/**
- * \brief Time output streamer.
- * 
- * Generates output such as "3.96ns"
- * \relates ns3::Time
- */
 std::ostream& operator<< (std::ostream& os, const Time & time);
-/**
- * \brief Time input streamer
- *
- * Uses the Time::Time (std::string) constructor
- * \relates ns3::Time
- */
 std::istream& operator>> (std::istream& is, Time & time);
 
 /**
@@ -605,7 +582,6 @@
  * Simulator::Schedule (Seconds (5.0), ...);
  * \endcode
  * \param seconds seconds value
- * \relates ns3::Time
  */
 inline Time Seconds (double seconds)
 {
@@ -621,7 +597,6 @@
  * Simulator::Schedule (MilliSeconds (5), ...);
  * \endcode
  * \param ms milliseconds value
- * \relates ns3::Time
  */
 inline Time MilliSeconds (uint64_t ms)
 {
@@ -636,7 +611,6 @@
  * Simulator::Schedule (MicroSeconds (5), ...);
  * \endcode
  * \param us microseconds value
- * \relates ns3::Time
  */
 inline Time MicroSeconds (uint64_t us)
 {
@@ -651,7 +625,6 @@
  * Simulator::Schedule (NanoSeconds (5), ...);
  * \endcode
  * \param ns nanoseconds value
- * \relates ns3::Time
  */
 inline Time NanoSeconds (uint64_t ns)
 {
@@ -666,7 +639,6 @@
  * Simulator::Schedule (PicoSeconds (5), ...);
  * \endcode
  * \param ps picoseconds value
- * \relates ns3::Time
  */
 inline Time PicoSeconds (uint64_t ps)
 {
@@ -681,7 +653,6 @@
  * Simulator::Schedule (FemtoSeconds (5), ...);
  * \endcode
  * \param fs femtoseconds value
- * \relates ns3::Time
  */
 inline Time FemtoSeconds (uint64_t fs)
 {
@@ -689,50 +660,26 @@
 }
 
 
-/**
- * \see Seconds(double)
- * \relates ns3::Time
- */ 
 inline Time Seconds (int64x64_t seconds)
 {
   return Time::From (seconds, Time::S);
 }
-/**
- * \see MilliSeconds(uint64_t)
- * \relates ns3::Time
- */ 
 inline Time MilliSeconds (int64x64_t ms)
 {
   return Time::From (ms, Time::MS);
 }
-/**
- * \see MicroSeconds(uint64_t)
- * \relates ns3::Time
- */ 
 inline Time MicroSeconds (int64x64_t us)
 {
   return Time::From (us, Time::US);
 }
-/**
- * \see NanoSeconds(uint64_t)
- * \relates ns3::Time
- */ 
 inline Time NanoSeconds (int64x64_t ns)
 {
   return Time::From (ns, Time::NS);
 }
-/**
- * \see PicoSeconds(uint64_t)
- * \relates ns3::Time
- */ 
 inline Time PicoSeconds (int64x64_t ps)
 {
   return Time::From (ps, Time::PS);
 }
-/**
- * \see FemtoSeconds(uint64_t)
- * \relates ns3::Time
- */ 
 inline Time FemtoSeconds (int64x64_t fs)
 {
   return Time::From (fs, Time::FS);
--- a/src/core/model/simulator.cc	Sat Dec 15 11:32:58 2012 -0800
+++ b/src/core/model/simulator.cc	Sat Dec 15 23:02:03 2012 -0800
@@ -157,9 +157,7 @@
 Simulator::Run (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  SimulatorImpl *impl = GetImpl ();
-  Time::FreezeResolution();
-  impl->Run ();
+  GetImpl ()->Run ();
 }
 
 void 
--- a/src/core/model/time.cc	Sat Dec 15 11:32:58 2012 -0800
+++ b/src/core/model/time.cc	Sat Dec 15 23:02:03 2012 -0800
@@ -26,14 +26,17 @@
 #include "string.h"
 #include "object.h"
 #include "config.h"
-#include "simulator.h"
+#include "log.h"
 #include <cmath>
 #include <sstream>
 
 namespace ns3 {
 
+NS_LOG_COMPONENT_DEFINE ("Time");
+
 Time::Time (const std::string& s)
 {
+  NS_LOG_FUNCTION (this << &s);
   std::string::size_type n = s.find_first_not_of ("+-0123456789.");
   if (n != std::string::npos)
     { // Found non-numeric
@@ -45,83 +48,62 @@
       if (trailer == std::string ("s"))
         {
           *this = Time::FromDouble (r, Time::S);
+          return;
         }
-      else if (trailer == std::string ("ms"))
+      if (trailer == std::string ("ms"))
         {
           *this = Time::FromDouble (r, Time::MS);
+          return;
         }
-      else if (trailer == std::string ("us"))
+      if (trailer == std::string ("us"))
         {
           *this = Time::FromDouble (r, Time::US);
+          return;
         }
-      else if (trailer == std::string ("ns"))
+      if (trailer == std::string ("ns"))
         {
           *this = Time::FromDouble (r, Time::NS);
+          return;
         }
-      else if (trailer == std::string ("ps"))
+      if (trailer == std::string ("ps"))
         {
           *this = Time::FromDouble (r, Time::PS);
+          return;
         }
-      else if (trailer == std::string ("fs"))
+      if (trailer == std::string ("fs"))
         {
           *this = Time::FromDouble (r, Time::FS);
+          return;
         }
-      else
-        {
-          NS_ABORT_MSG ("Can't Parse Time " << s);
-        }
+      NS_ABORT_MSG ("Can't Parse Time " << s);
     }
-  else
-    {
-      // they didn't provide units, assume seconds
-      std::istringstream iss;
-      iss.str (s);
-      double v;
-      iss >> v;
-      *this = Time::FromDouble (v, Time::S);
-    }
-  
-  Time::Track (this);
+  // else
+  // they didn't provide units, assume seconds
+  std::istringstream iss;
+  iss.str (s);
+  double v;
+  iss >> v;
+  *this = Time::FromDouble (v, Time::S);
 }
 
-// static
 struct Time::Resolution
-Time::SetDefaultNsResolution (void)
+Time::GetNsResolution (void)
 {
+  NS_LOG_FUNCTION_NOARGS ();
   struct Resolution resolution;
-  DoSetResolution (Time::NS, &resolution);
+  SetResolution (Time::NS, &resolution);
   return resolution;
 }
-
-// static
 void 
 Time::SetResolution (enum Unit resolution)
 {
+  NS_LOG_FUNCTION (resolution);
   SetResolution (resolution, PeekResolution ());
 }
-
-// static
-enum Time::Unit
-Time::GetResolution (void)
-{
-  return PeekResolution ()->unit;
-}
-
-// static
 void 
 Time::SetResolution (enum Unit unit, struct Resolution *resolution)
 {
-  if (Time::GetTimesSet() == 0)
-    {
-      NS_FATAL_ERROR("The resolution has already been set once. You cannot set it again.");
-    }
-  Time::FreezeResolution(unit);
-  Time::DoSetResolution(unit, resolution);
-}
-// static
-void 
-Time::DoSetResolution (enum Unit unit, struct Resolution *resolution)
-{
+  NS_LOG_FUNCTION (unit << resolution);
   int8_t power [LAST] = { 15, 12, 9, 6, 3, 0};
   for (int i = 0; i < Time::LAST; i++)
     {
@@ -154,90 +136,18 @@
     }
   resolution->unit = unit;
 }
-
-// static
-Time::TimesSet **
-Time::PeekTimesSet (void)
+enum Time::Unit
+Time::GetResolution (void)
 {
-  static TimesSet *times = new TimesSet();
-  return &times;
-}
-
-// static
-Time::TimesSet *
-Time::GetTimesSet ()
-{
-  TimesSet **ptimes = PeekTimesSet();
-  return *ptimes;
+  NS_LOG_FUNCTION_NOARGS ();
+  return PeekResolution ()->unit;
 }
 
-// static
-void
-Time::FreezeResolution (void)
-{
-  TimesSet **ptimes = PeekTimesSet();
-  if (*ptimes == 0)
-    {
-      // We froze the resolution more than once: no big deal
-      return;
-    }
-  delete *ptimes;
-  *ptimes = 0;
-}
-void
-Time::FreezeResolution(enum Time::Unit unit)
-{
-  // We are careful to remove the timeset _first_ because the code in the loop below
-  // actually invokes a Time constructor which invokes the Track method which
-  // adds things to the array we are iterating over.
-  TimesSet **ptimes = PeekTimesSet();
-  TimesSet *times = *ptimes;
-  *ptimes = 0;
-  
-  for ( TimesSet::iterator it = times->begin();
-        it != times->end();
-        it++ )
-    {
-      Time * const tp = *it;
-      (*tp) = tp->ToInteger (unit);
-    }
-
-  delete times;
-}
-
-// static
-void
-Time::Track (Time * const time)
-{
-  NS_ASSERT (time != 0);
-
-  TimesSet * times = GetTimesSet();
-  if (times != 0)
-    {
-      std::pair< TimesSet::iterator, bool> ret;
-      ret = times->insert ( time);
-    }
-}
-
-// static
-void
-Time::UnTrack (Time * const time)
-{
-  NS_ASSERT (time != 0);
-  TimesSet * times = GetTimesSet ();
-  if (times != 0)
-    {
-      NS_ASSERT_MSG (times->count (time) == 1,
-		     "Time object " << time << " registered "
-		     << times->count (time) << " times (should be 1)." );
-
-      times->erase (time);
-    }
-}
 
 std::ostream&
 operator<< (std::ostream& os, const Time & time)
 {
+  NS_LOG_FUNCTION (&os << time);
   std::string unit;
   switch (Time::GetResolution ())
     {
@@ -270,6 +180,7 @@
 }
 std::istream& operator>> (std::istream& is, Time & time)
 {
+  NS_LOG_FUNCTION (&is << time);
   std::string value;
   is >> value;
   time = Time (value);
--- a/src/core/test/time-test-suite.cc	Sat Dec 15 11:32:58 2012 -0800
+++ b/src/core/test/time-test-suite.cc	Sat Dec 15 23:02:03 2012 -0800
@@ -27,26 +27,31 @@
 class TimeSimpleTestCase : public TestCase
 {
 public:
-  TimeSimpleTestCase ();
+  TimeSimpleTestCase (enum Time::Unit resolution);
 private:
   virtual void DoSetup (void);
   virtual void DoRun (void);
   virtual void DoTeardown (void);
+  enum Time::Unit m_originalResolution;
+  enum Time::Unit m_resolution;
 };
 
-TimeSimpleTestCase::TimeSimpleTestCase ()
-  : TestCase ("Sanity check of common time operations")
+TimeSimpleTestCase::TimeSimpleTestCase (enum Time::Unit resolution)
+  : TestCase ("Sanity check of common time operations"),
+    m_resolution (resolution)
 {
 }
 
 void
 TimeSimpleTestCase::DoSetup (void)
 {
+  m_originalResolution = Time::GetResolution ();
 }
 
 void
 TimeSimpleTestCase::DoRun (void)
 {
+  Time::SetResolution (m_resolution);
   NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (1.0).GetSeconds (), 1.0, TimeStep (1).GetSeconds (), 
                              "is 1 really 1 ?");
   NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (10.0).GetSeconds (), 10.0, TimeStep (1).GetSeconds (), 
@@ -65,18 +70,12 @@
   NS_TEST_ASSERT_MSG_EQ (FemtoSeconds (1).GetFemtoSeconds (), 1, 
                          "is 1fs really 1fs ?");
 #endif
-
-  Time ten = NanoSeconds (10);
-  int64_t tenValue = ten.GetInteger ();
-  Time::SetResolution (Time::PS);
-  int64_t tenKValue = ten.GetInteger ();
-  NS_TEST_ASSERT_MSG_EQ (tenValue * 1000, tenKValue,
-                         "change resolution to PS");
 }
 
 void 
 TimeSimpleTestCase::DoTeardown (void)
 {
+  Time::SetResolution (m_originalResolution);
 }
 
 class TimesWithSignsTestCase : public TestCase
@@ -140,7 +139,7 @@
   TimeTestSuite ()
     : TestSuite ("time", UNIT)
   {
-    AddTestCase (new TimeSimpleTestCase ());
+    AddTestCase (new TimeSimpleTestCase (Time::US));
     AddTestCase (new TimesWithSignsTestCase ());
   }
 } g_timeTestSuite;