try to nail down some of the subtler aspects of calling Time::SetResolution
authorMathieu Lacage <mathieu.lacage@cutebugs.net>
Wed, 12 Dec 2012 04:50:46 -0500
changeset 9187 8ef8d8bae350
parent 9186 8934b7c0c1cb
child 9188 7c80515eab0c
try to nail down some of the subtler aspects of calling Time::SetResolution
src/core/model/nstime.h
src/core/model/time.cc
--- a/src/core/model/nstime.h	Wed Dec 12 04:10:25 2012 -0500
+++ b/src/core/model/nstime.h	Wed Dec 12 04:50:46 2012 -0500
@@ -293,6 +293,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);
   /**
@@ -449,6 +452,8 @@
 
   static struct Resolution SetDefaultNsResolution (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
--- a/src/core/model/time.cc	Wed Dec 12 04:10:25 2012 -0500
+++ b/src/core/model/time.cc	Wed Dec 12 04:50:46 2012 -0500
@@ -89,7 +89,7 @@
 Time::SetDefaultNsResolution (void)
 {
   struct Resolution resolution;
-  SetResolution (Time::NS, &resolution);
+  DoSetResolution (Time::NS, &resolution);
   return resolution;
 }
 
@@ -111,12 +111,17 @@
 void 
 Time::SetResolution (enum Unit unit, struct Resolution *resolution)
 {
-  TimesSet * times = GetTimesSet();
-  if (times == 0)
+  if (Time::GetTimesSet() == 0)
     {
-      NS_FATAL_ERROR("It is not legal to try to set the resolution " \
-                     "_after_ it has been frozen by Simulator::Run");
+      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)
+{
   int8_t power [LAST] = { 15, 12, 9, 6, 3, 0};
   for (int i = 0; i < Time::LAST; i++)
     {
@@ -170,24 +175,34 @@
 void
 Time::FreezeResolution (void)
 {
-  TimesSet * times = GetTimesSet ();
-  if (times == 0)
+  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 (Time::GetResolution());
+      (*tp) = tp->ToInteger (unit);
     }
 
-  TimesSet **ptimes = PeekTimesSet();
-  delete *ptimes;
-  *ptimes = 0;
+  delete times;
 }
 
 // static
@@ -197,7 +212,7 @@
   NS_ASSERT (time != 0);
 
   TimesSet * times = GetTimesSet();
-  if (times)
+  if (times != 0)
     {
       std::pair< TimesSet::iterator, bool> ret;
       ret = times->insert ( time);
@@ -210,7 +225,7 @@
 {
   NS_ASSERT (time != 0);
   TimesSet * times = GetTimesSet ();
-  if (times)
+  if (times != 0)
     {
       NS_ASSERT_MSG (times->count (time) == 1,
 		     "Time object " << time << " registered "