make simulator implementation replaceable via global default value
authorCraig Dowell <craigdo@ee.washington.edu>
Fri, 18 Jul 2008 21:51:31 -0700
changeset 3470 21022872009d
parent 3469 9e763021e045
child 3471 0896bd4a38dd
make simulator implementation replaceable via global default value
src/simulator/default-simulator-impl.cc
src/simulator/default-simulator-impl.h
src/simulator/simulator-impl.cc
src/simulator/simulator-impl.h
src/simulator/simulator.cc
src/simulator/simulator.h
src/simulator/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/default-simulator-impl.cc	Fri Jul 18 21:51:31 2008 -0700
@@ -0,0 +1,331 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "simulator.h"
+#include "default-simulator-impl.h"
+#include "scheduler.h"
+#include "event-impl.h"
+
+#include "ns3/ptr.h"
+#include "ns3/pointer.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+
+#include <math.h>
+
+NS_LOG_COMPONENT_DEFINE ("DefaultSimulatorImpl");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (DefaultSimulatorImpl);
+
+TypeId
+DefaultSimulatorImpl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::DefaultSimulatorImpl")
+    .SetParent<Object> ()
+    .AddConstructor<DefaultSimulatorImpl> ()
+    ;
+  return tid;
+}
+
+DefaultSimulatorImpl::DefaultSimulatorImpl ()
+{
+  m_stop = false;
+  m_stopAt = 0;
+  // uids are allocated from 4.
+  // uid 0 is "invalid" events
+  // uid 1 is "now" events
+  // uid 2 is "destroy" events
+  m_uid = 4; 
+  // before ::Run is entered, the m_currentUid will be zero
+  m_currentUid = 0;
+  m_logEnable = false;
+  m_currentTs = 0;
+  m_unscheduledEvents = 0;
+}
+
+DefaultSimulatorImpl::~DefaultSimulatorImpl ()
+{
+  while (!m_events->IsEmpty ())
+    {
+      EventId next = m_events->RemoveNext ();
+    }
+  m_events = 0;
+}
+
+void
+DefaultSimulatorImpl::Destroy ()
+{
+  while (!m_destroyEvents.empty ()) 
+    {
+      Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
+      m_destroyEvents.pop_front ();
+      NS_LOG_LOGIC ("handle destroy " << ev);
+      if (!ev->IsCancelled ())
+        {
+          ev->Invoke ();
+        }
+    }
+}
+
+void
+DefaultSimulatorImpl::SetScheduler (Ptr<Scheduler> scheduler)
+{
+  if (m_events != 0)
+    {
+      while (!m_events->IsEmpty ())
+        {
+          EventId next = m_events->RemoveNext ();
+          scheduler->Insert (next);
+        }
+    }
+  m_events = scheduler;
+}
+
+Ptr<Scheduler>
+DefaultSimulatorImpl::GetScheduler (void) const
+{
+  return m_events;
+}
+
+void
+DefaultSimulatorImpl::EnableLogTo (char const *filename)
+{
+  m_log.open (filename);
+  m_logEnable = true;
+}
+
+void
+DefaultSimulatorImpl::ProcessOneEvent (void)
+{
+  EventId next = m_events->RemoveNext ();
+
+  NS_ASSERT (next.GetTs () >= m_currentTs);
+  --m_unscheduledEvents;
+
+  NS_LOG_LOGIC ("handle " << next.GetTs ());
+  m_currentTs = next.GetTs ();
+  m_currentUid = next.GetUid ();
+  if (m_logEnable) 
+    {
+      m_log << "e "<<next.GetUid () << " " << next.GetTs () << std::endl;
+    }
+  EventImpl *event = next.PeekEventImpl ();
+  event->Invoke ();
+}
+
+bool 
+DefaultSimulatorImpl::IsFinished (void) const
+{
+  return m_events->IsEmpty ();
+}
+
+uint64_t
+DefaultSimulatorImpl::NextTs (void) const
+{
+  NS_ASSERT (!m_events->IsEmpty ());
+  EventId id = m_events->PeekNext ();
+  return id.GetTs ();
+}
+
+Time
+DefaultSimulatorImpl::Next (void) const
+{
+  return TimeStep (NextTs ());
+}
+
+void
+DefaultSimulatorImpl::Run (void)
+{
+
+  while (!m_events->IsEmpty () && !m_stop && 
+         (m_stopAt == 0 || m_stopAt > NextTs ())) 
+    {
+      ProcessOneEvent ();
+    }
+
+  // If the simulator stopped naturally by lack of events, make a
+  // consistency test to check that we didn't lose any events along the way.
+  NS_ASSERT(!m_events->IsEmpty () || m_unscheduledEvents == 0);
+
+  m_log.close ();
+}
+
+void 
+DefaultSimulatorImpl::Stop (void)
+{
+  m_stop = true;
+}
+
+void 
+DefaultSimulatorImpl::Stop (Time const &time)
+{
+  NS_ASSERT (time.IsPositive ());
+  Time absolute = Simulator::Now () + time;
+  m_stopAt = absolute.GetTimeStep ();
+}
+
+EventId
+DefaultSimulatorImpl::Schedule (Time const &time, const Ptr<EventImpl> &event)
+{
+  NS_ASSERT (time.IsPositive ());
+  NS_ASSERT (time >= TimeStep (m_currentTs));
+  uint64_t ts = (uint64_t) time.GetTimeStep ();
+  EventId id (event, ts, m_uid);
+  if (m_logEnable) 
+    {
+      m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
+            <<m_uid<<" "<<time.GetTimeStep () << std::endl;
+    }
+  m_uid++;
+  ++m_unscheduledEvents;
+  m_events->Insert (id);
+  return id;
+}
+
+EventId
+DefaultSimulatorImpl::ScheduleNow (const Ptr<EventImpl> &event)
+{
+  EventId id (event, m_currentTs, m_uid);
+  if (m_logEnable) 
+    {
+      m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
+            <<m_uid<<" "<<m_currentTs << std::endl;
+    }
+  m_uid++;
+  ++m_unscheduledEvents;
+  m_events->Insert (id);
+  return id;
+}
+
+EventId
+DefaultSimulatorImpl::ScheduleDestroy (const Ptr<EventImpl> &event)
+{
+  EventId id (event, m_currentTs, 2);
+  m_destroyEvents.push_back (id);
+  if (m_logEnable) 
+  {
+    m_log << "id " << m_currentUid << " " << Now ().GetTimeStep () << " "
+          << m_uid << std::endl;
+  }
+  m_uid++;
+  return id;
+}
+
+Time
+DefaultSimulatorImpl::Now (void) const
+{
+  return TimeStep (m_currentTs);
+}
+
+Time 
+DefaultSimulatorImpl::GetDelayLeft (const EventId &id) const
+{
+  if (IsExpired (id))
+    {
+      return TimeStep (0);
+    }
+  else
+    {
+      return TimeStep (id.GetTs () - m_currentTs);
+    }
+}
+
+void
+DefaultSimulatorImpl::Remove (const EventId &ev)
+{
+  if (ev.GetUid () == 2)
+    {
+      // destroy events.
+      for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
+        {
+          if (*i == ev)
+            {
+              m_destroyEvents.erase (i);
+              break;
+            }
+         }
+      return;
+    }
+  if (IsExpired (ev))
+    {
+      return;
+    }
+  m_events->Remove (ev);
+  Cancel (ev);
+
+  if (m_logEnable) 
+    {
+      m_log << "r " << m_currentUid << " " << m_currentTs << " "
+            << ev.GetUid () << " " << ev.GetTs () << std::endl;
+    }
+  --m_unscheduledEvents;
+}
+
+void
+DefaultSimulatorImpl::Cancel (const EventId &id)
+{
+  if (!IsExpired (id))
+    {
+      id.PeekEventImpl ()->Cancel ();
+    }
+}
+
+bool
+DefaultSimulatorImpl::IsExpired (const EventId &ev) const
+{
+  if (ev.GetUid () == 2)
+    {
+      // destroy events.
+      for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
+        {
+          if (*i == ev)
+            {
+              return false;
+            }
+         }
+      return true;
+    }
+  if (ev.PeekEventImpl () == 0 ||
+      ev.GetTs () < m_currentTs ||
+      (ev.GetTs () == m_currentTs &&
+       ev.GetUid () <= m_currentUid) ||
+      ev.PeekEventImpl ()->IsCancelled ()) 
+    {
+      return true;
+    }
+  else
+    {
+      return false;
+    }
+}
+
+Time 
+DefaultSimulatorImpl::GetMaximumSimulationTime (void) const
+{
+  // XXX: I am fairly certain other compilers use other non-standard
+  // post-fixes to indicate 64 bit constants.
+  return TimeStep (0x7fffffffffffffffLL);
+}
+
+}; // namespace ns3
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/default-simulator-impl.h	Fri Jul 18 21:51:31 2008 -0700
@@ -0,0 +1,90 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef DEFAULT_SIMULATOR_IMPL_H
+#define DEFAULT_SIMULATOR_IMPL_H
+
+#include "simulator-impl.h"
+
+#include "scheduler.h"
+#include "event-impl.h"
+
+#include "ns3/ptr.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+
+#include <list>
+#include <fstream>
+
+namespace ns3 {
+
+  class DefaultSimulatorImpl : public SimulatorImpl
+{
+public:
+  static TypeId GetTypeId (void);
+
+  DefaultSimulatorImpl ();
+  ~DefaultSimulatorImpl ();
+
+  void Destroy ();
+
+  void EnableLogTo (char const *filename);
+
+  bool IsFinished (void) const;
+  Time Next (void) const;
+  void Stop (void);
+  void Stop (Time const &time);
+  EventId Schedule (Time const &time, const Ptr<EventImpl> &event);
+  EventId ScheduleNow (const Ptr<EventImpl> &event);
+  EventId ScheduleDestroy (const Ptr<EventImpl> &event);
+  void Remove (const EventId &ev);
+  void Cancel (const EventId &ev);
+  bool IsExpired (const EventId &ev) const;
+  void Run (void);
+  Time Now (void) const;
+  Time GetDelayLeft (const EventId &id) const;
+  Time GetMaximumSimulationTime (void) const;
+
+  void SetScheduler (Ptr<Scheduler> scheduler);
+  Ptr<Scheduler> GetScheduler (void) const;
+
+private:
+  void ProcessOneEvent (void);
+  uint64_t NextTs (void) const;
+
+  typedef std::list<EventId> DestroyEvents;
+  DestroyEvents m_destroyEvents;
+  uint64_t m_stopAt;
+  bool m_stop;
+  Ptr<Scheduler> m_events;
+  uint32_t m_uid;
+  uint32_t m_currentUid;
+  uint64_t m_currentTs;
+  std::ofstream m_log;
+  std::ifstream m_inputLog;
+  bool m_logEnable;
+  // number of events that have been inserted but not yet scheduled,
+  // not counting the "destroy" events; this is used for validation
+  int m_unscheduledEvents;
+};
+
+} // namespace ns3
+
+#endif /* DEFAULT_SIMULATOR_IMPL_H */
--- a/src/simulator/simulator-impl.cc	Thu Jul 17 23:52:59 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "simulator.h"
-#include "simulator-impl.h"
-#include "scheduler.h"
-#include "event-impl.h"
-
-#include "ns3/ptr.h"
-#include "ns3/pointer.h"
-#include "ns3/assert.h"
-#include "ns3/log.h"
-
-#include <math.h>
-
-NS_LOG_COMPONENT_DEFINE ("SimulatorImpl");
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (SimulatorImpl);
-
-TypeId
-SimulatorImpl::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::SimulatorImpl")
-    .SetParent<Object> ()
-    .AddConstructor<SimulatorImpl> ()
-    ;
-  return tid;
-}
-
-SimulatorImpl::SimulatorImpl ()
-{
-  m_stop = false;
-  m_stopAt = 0;
-  // uids are allocated from 4.
-  // uid 0 is "invalid" events
-  // uid 1 is "now" events
-  // uid 2 is "destroy" events
-  m_uid = 4; 
-  // before ::Run is entered, the m_currentUid will be zero
-  m_currentUid = 0;
-  m_logEnable = false;
-  m_currentTs = 0;
-  m_unscheduledEvents = 0;
-}
-
-SimulatorImpl::~SimulatorImpl ()
-{
-  while (!m_events->IsEmpty ())
-    {
-      EventId next = m_events->RemoveNext ();
-    }
-  m_events = 0;
-}
-
-void
-SimulatorImpl::Destroy ()
-{
-  while (!m_destroyEvents.empty ()) 
-    {
-      Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
-      m_destroyEvents.pop_front ();
-      NS_LOG_LOGIC ("handle destroy " << ev);
-      if (!ev->IsCancelled ())
-        {
-          ev->Invoke ();
-        }
-    }
-}
-
-void
-SimulatorImpl::SetScheduler (Ptr<Scheduler> scheduler)
-{
-  if (m_events != 0)
-    {
-      while (!m_events->IsEmpty ())
-        {
-          EventId next = m_events->RemoveNext ();
-          scheduler->Insert (next);
-        }
-    }
-  m_events = scheduler;
-}
-
-Ptr<Scheduler>
-SimulatorImpl::GetScheduler (void) const
-{
-  return m_events;
-}
-
-void
-SimulatorImpl::EnableLogTo (char const *filename)
-{
-  m_log.open (filename);
-  m_logEnable = true;
-}
-
-void
-SimulatorImpl::ProcessOneEvent (void)
-{
-  EventId next = m_events->RemoveNext ();
-
-  NS_ASSERT (next.GetTs () >= m_currentTs);
-  --m_unscheduledEvents;
-
-  NS_LOG_LOGIC ("handle " << next.GetTs ());
-  m_currentTs = next.GetTs ();
-  m_currentUid = next.GetUid ();
-  if (m_logEnable) 
-    {
-      m_log << "e "<<next.GetUid () << " " << next.GetTs () << std::endl;
-    }
-  EventImpl *event = next.PeekEventImpl ();
-  event->Invoke ();
-}
-
-bool 
-SimulatorImpl::IsFinished (void) const
-{
-  return m_events->IsEmpty ();
-}
-
-uint64_t
-SimulatorImpl::NextTs (void) const
-{
-  NS_ASSERT (!m_events->IsEmpty ());
-  EventId id = m_events->PeekNext ();
-  return id.GetTs ();
-}
-
-Time
-SimulatorImpl::Next (void) const
-{
-  return TimeStep (NextTs ());
-}
-
-void
-SimulatorImpl::Run (void)
-{
-
-  while (!m_events->IsEmpty () && !m_stop && 
-         (m_stopAt == 0 || m_stopAt > NextTs ())) 
-    {
-      ProcessOneEvent ();
-    }
-
-  // If the simulator stopped naturally by lack of events, make a
-  // consistency test to check that we didn't lose any events along the way.
-  NS_ASSERT(!m_events->IsEmpty () || m_unscheduledEvents == 0);
-
-  m_log.close ();
-}
-
-void 
-SimulatorImpl::Stop (void)
-{
-  m_stop = true;
-}
-
-void 
-SimulatorImpl::Stop (Time const &time)
-{
-  NS_ASSERT (time.IsPositive ());
-  Time absolute = Simulator::Now () + time;
-  m_stopAt = absolute.GetTimeStep ();
-}
-
-EventId
-SimulatorImpl::Schedule (Time const &time, const Ptr<EventImpl> &event)
-{
-  NS_ASSERT (time.IsPositive ());
-  NS_ASSERT (time >= TimeStep (m_currentTs));
-  uint64_t ts = (uint64_t) time.GetTimeStep ();
-  EventId id (event, ts, m_uid);
-  if (m_logEnable) 
-    {
-      m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
-            <<m_uid<<" "<<time.GetTimeStep () << std::endl;
-    }
-  m_uid++;
-  ++m_unscheduledEvents;
-  m_events->Insert (id);
-  return id;
-}
-
-EventId
-SimulatorImpl::ScheduleNow (const Ptr<EventImpl> &event)
-{
-  EventId id (event, m_currentTs, m_uid);
-  if (m_logEnable) 
-    {
-      m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
-            <<m_uid<<" "<<m_currentTs << std::endl;
-    }
-  m_uid++;
-  ++m_unscheduledEvents;
-  m_events->Insert (id);
-  return id;
-}
-
-EventId
-SimulatorImpl::ScheduleDestroy (const Ptr<EventImpl> &event)
-{
-  EventId id (event, m_currentTs, 2);
-  m_destroyEvents.push_back (id);
-  if (m_logEnable) 
-  {
-    m_log << "id " << m_currentUid << " " << Now ().GetTimeStep () << " "
-          << m_uid << std::endl;
-  }
-  m_uid++;
-  return id;
-}
-
-Time
-SimulatorImpl::Now (void) const
-{
-  return TimeStep (m_currentTs);
-}
-
-Time 
-SimulatorImpl::GetDelayLeft (const EventId &id) const
-{
-  if (IsExpired (id))
-    {
-      return TimeStep (0);
-    }
-  else
-    {
-      return TimeStep (id.GetTs () - m_currentTs);
-    }
-}
-
-void
-SimulatorImpl::Remove (const EventId &ev)
-{
-  if (ev.GetUid () == 2)
-    {
-      // destroy events.
-      for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
-        {
-          if (*i == ev)
-            {
-              m_destroyEvents.erase (i);
-              break;
-            }
-         }
-      return;
-    }
-  if (IsExpired (ev))
-    {
-      return;
-    }
-  m_events->Remove (ev);
-  Cancel (ev);
-
-  if (m_logEnable) 
-    {
-      m_log << "r " << m_currentUid << " " << m_currentTs << " "
-            << ev.GetUid () << " " << ev.GetTs () << std::endl;
-    }
-  --m_unscheduledEvents;
-}
-
-void
-SimulatorImpl::Cancel (const EventId &id)
-{
-  if (!IsExpired (id))
-    {
-      id.PeekEventImpl ()->Cancel ();
-    }
-}
-
-bool
-SimulatorImpl::IsExpired (const EventId &ev) const
-{
-  if (ev.GetUid () == 2)
-    {
-      // destroy events.
-      for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
-        {
-          if (*i == ev)
-            {
-              return false;
-            }
-         }
-      return true;
-    }
-  if (ev.PeekEventImpl () == 0 ||
-      ev.GetTs () < m_currentTs ||
-      (ev.GetTs () == m_currentTs &&
-       ev.GetUid () <= m_currentUid) ||
-      ev.PeekEventImpl ()->IsCancelled ()) 
-    {
-      return true;
-    }
-  else
-    {
-      return false;
-    }
-}
-
-Time 
-SimulatorImpl::GetMaximumSimulationTime (void) const
-{
-  // XXX: I am fairly certain other compilers use other non-standard
-  // post-fixes to indicate 64 bit constants.
-  return TimeStep (0x7fffffffffffffffLL);
-}
-
-}; // namespace ns3
-
-
--- a/src/simulator/simulator-impl.h	Thu Jul 17 23:52:59 2008 -0700
+++ b/src/simulator/simulator-impl.h	Fri Jul 18 21:51:31 2008 -0700
@@ -23,6 +23,7 @@
 
 #include "scheduler.h"
 #include "event-impl.h"
+#include "nstime.h"
 
 #include "ns3/ptr.h"
 #include "ns3/assert.h"
@@ -36,51 +37,24 @@
 class SimulatorImpl : public Object
 {
 public:
-  static TypeId GetTypeId (void);
-
-  SimulatorImpl ();
-  ~SimulatorImpl ();
-
-  void Destroy ();
-
-  void EnableLogTo (char const *filename);
-
-  bool IsFinished (void) const;
-  Time Next (void) const;
-  void Stop (void);
-  void Stop (Time const &time);
-  EventId Schedule (Time const &time, const Ptr<EventImpl> &event);
-  EventId ScheduleNow (const Ptr<EventImpl> &event);
-  EventId ScheduleDestroy (const Ptr<EventImpl> &event);
-  void Remove (const EventId &ev);
-  void Cancel (const EventId &ev);
-  bool IsExpired (const EventId &ev) const;
-  void Run (void);
-  Time Now (void) const;
-  Time GetDelayLeft (const EventId &id) const;
-  Time GetMaximumSimulationTime (void) const;
-
-  void SetScheduler (Ptr<Scheduler> scheduler);
-  Ptr<Scheduler> GetScheduler (void) const;
-
-private:
-  void ProcessOneEvent (void);
-  uint64_t NextTs (void) const;
-
-  typedef std::list<EventId> DestroyEvents;
-  DestroyEvents m_destroyEvents;
-  uint64_t m_stopAt;
-  bool m_stop;
-  Ptr<Scheduler> m_events;
-  uint32_t m_uid;
-  uint32_t m_currentUid;
-  uint64_t m_currentTs;
-  std::ofstream m_log;
-  std::ifstream m_inputLog;
-  bool m_logEnable;
-  // number of events that have been inserted but not yet scheduled,
-  // not counting the "destroy" events; this is used for validation
-  int m_unscheduledEvents;
+  virtual void Destroy () = 0;
+  virtual void EnableLogTo (char const *filename) = 0;
+  virtual bool IsFinished (void) const = 0;
+  virtual Time Next (void) const = 0;
+  virtual void Stop (void) = 0;
+  virtual void Stop (Time const &time) = 0;
+  virtual EventId Schedule (Time const &time, const Ptr<EventImpl> &event) = 0;
+  virtual EventId ScheduleNow (const Ptr<EventImpl> &event) = 0;
+  virtual EventId ScheduleDestroy (const Ptr<EventImpl> &event) = 0;
+  virtual void Remove (const EventId &ev) = 0;
+  virtual void Cancel (const EventId &ev) = 0;
+  virtual bool IsExpired (const EventId &ev) const = 0;
+  virtual void Run (void) = 0;
+  virtual Time Now (void) const = 0;
+  virtual Time GetDelayLeft (const EventId &id) const = 0;
+  virtual Time GetMaximumSimulationTime (void) const = 0;
+  virtual void SetScheduler (Ptr<Scheduler> scheduler) = 0;
+  virtual Ptr<Scheduler> GetScheduler (void) const = 0;
 };
 
 } // namespace ns3
--- a/src/simulator/simulator.cc	Thu Jul 17 23:52:59 2008 -0700
+++ b/src/simulator/simulator.cc	Fri Jul 18 21:51:31 2008 -0700
@@ -20,12 +20,15 @@
 
 #include "simulator.h"
 #include "simulator-impl.h"
+#include "default-simulator-impl.h"
 #include "scheduler.h"
 #include "map-scheduler.h"
 #include "event-impl.h"
 
 #include "ns3/ptr.h"
-#include "ns3/pointer.h"
+#include "ns3/string.h"
+#include "ns3/object-factory.h"
+#include "ns3/global-value.h"
 #include "ns3/assert.h"
 #include "ns3/log.h"
 
@@ -39,38 +42,56 @@
 
 namespace ns3 {
 
+GlobalValue g_simTypeImpl = GlobalValue ("SimulatorImplementationType", 
+  "The object class to use as the simulator implementation",
+  StringValue ("ns3::DefaultSimulatorImpl"),
+  MakeStringChecker ());
+
+Ptr<SimulatorImpl> Simulator::m_impl = 0;
+
 #ifdef NS3_LOG_ENABLE
+
+//
+// Note:  Calls that take TimePrinter as a parameter are defined as nothing
+// in the logging module if NS3_LOG_ENABLE is not defined.
+// 
+
 static void
 TimePrinter (std::ostream &os)
 {
   os << Simulator::Now ();
 }
+
 #endif /* NS3_LOG_ENABLE */
 
-Ptr<SimulatorImpl> Simulator::m_impl = 0;
-
-Ptr<SimulatorImpl>
+SimulatorImpl *
 Simulator::GetImpl (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
 
   if (m_impl == 0) 
     {
-      /* Note: we call LogSetTimePrinter below _after_ calling CreateObject 
-       * because CreateObject can trigger calls to the logging framework which
-       * would call the TimePrinter function above which would call 
-       * Simulator::Now which would call Simulator::GetImpl, and, thus, get 
-       * us in an infinite recursion until the stack explodes.
-       */
-      m_impl = CreateObject<SimulatorImpl> ();
+      ObjectFactory factory;
+      StringValue s;
+
+      g_simTypeImpl.GetValue (s);
+      factory.SetTypeId (s.Get ());
+      m_impl = factory.Create<SimulatorImpl> ();
 
       Ptr<Scheduler> scheduler = CreateObject<MapScheduler> ();
       m_impl->SetScheduler (scheduler);
 
+//
+// Note: we call LogSetTimePrinter _after_ creating the implementation
+// object because the act of creation can trigger calls to the logging 
+// framework which would call the TimePrinter function which would call 
+// Simulator::Now which would call Simulator::GetImpl, and, thus, get us 
+// in an infinite recursion until the stack explodes.
+//
       LogSetTimePrinter (&TimePrinter);
     }
   NS_LOG_LOGIC ("priv " << m_impl);
-  return m_impl;
+  return PeekPointer (m_impl);
 }
 
 void
--- a/src/simulator/simulator.h	Thu Jul 17 23:52:59 2008 -0700
+++ b/src/simulator/simulator.h	Fri Jul 18 21:51:31 2008 -0700
@@ -21,18 +21,19 @@
 #ifndef SIMULATOR_H
 #define SIMULATOR_H
 
-#include <stdint.h>
 #include "event-id.h"
 #include "event-impl.h"
 #include "nstime.h"
 #include "scheduler.h"
+
 #include "ns3/type-traits.h"
 
+#include <stdint.h>
+#include <string>
+
 namespace ns3 {
 
-
 class SimulatorImpl;
-class SchedulerFactory;
 
 /**
  * \ingroup simulator
@@ -56,6 +57,20 @@
 {
 public:
   /**
+   * \param impl a new simulator implementation
+   *
+   * The simulator provides a mechanism to swap out different implementations.
+   * For example, the default implementation is a single-threaded simulator
+   * that performs no realtime synchronization.  By calling this method, you
+   * can substitute in a new simulator implementation that might be multi-
+   * threaded and synchronize events to a realtime clock.
+   *
+   * The simulator implementation can be set when the simulator is not 
+   * running.
+   */
+  static void SetImplementation (Ptr<SimulatorImpl> impl);
+
+  /**
    * \param scheduler a new event scheduler
    *
    * The event scheduler can be set at any time: the events scheduled
@@ -91,7 +106,6 @@
    */
   static void Destroy (void);
 
-
   /**
    * If there any any events lefts to be scheduled, return
    * true. Return false otherwise.
@@ -113,12 +127,14 @@
    *     is greater than or equal to the stop time.
    */
   static void Run (void);
+
   /**
    * If an event invokes this method, it will be the last
    * event scheduled by the Simulator::run method before
    * returning to the caller.
    */
   static void Stop (void);
+
   /**
    * Force the Simulator::run method to return to the caller when the
    * expiration time of the next event to be processed is greater than
@@ -140,6 +156,7 @@
    */
   template <typename MEM, typename OBJ>
   static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj);
+
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -149,6 +166,7 @@
    */
   template <typename MEM, typename OBJ, typename T1>
   static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1);
+
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -159,6 +177,7 @@
    */
   template <typename MEM, typename OBJ, typename T1, typename T2>
   static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2);
+
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -171,6 +190,7 @@
   template <typename MEM, typename OBJ, 
             typename T1, typename T2, typename T3>
   static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3);
+
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -184,6 +204,7 @@
   template <typename MEM, typename OBJ, 
             typename T1, typename T2, typename T3, typename T4>
   static EventId Schedule (Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4);
+
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -205,6 +226,7 @@
    * @returns an id for the scheduled event.
    */
   static EventId Schedule (Time const &time, void (*f) (void));
+
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -213,6 +235,7 @@
    */
   template <typename U1, typename T1>
   static EventId Schedule (Time const &time, void (*f) (U1), T1 a1);
+
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -222,6 +245,7 @@
    */
   template <typename U1, typename U2, typename T1, typename T2>
   static EventId Schedule (Time const &time, void (*f) (U1,U2), T1 a1, T2 a2);
+
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -232,6 +256,7 @@
    */
   template <typename U1, typename U2, typename U3, typename T1, typename T2, typename T3>
   static EventId Schedule (Time const &time, void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3);
+
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -244,6 +269,7 @@
   template <typename U1, typename U2, typename U3, typename U4, 
             typename T1, typename T2, typename T3, typename T4>
   static EventId Schedule (Time const &time, void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4);
+
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -258,7 +284,6 @@
             typename T1, typename T2, typename T3, typename T4, typename T5>
   static EventId Schedule (Time const &time, void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
 
-
   /**
    * Schedule an event to expire Now. All events scheduled to
    * to expire "Now" are scheduled FIFO, after all normal events
@@ -269,6 +294,7 @@
    */
   template <typename MEM, typename OBJ>
   static EventId ScheduleNow (MEM mem_ptr, OBJ obj);
+
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -277,6 +303,7 @@
   template <typename MEM, typename OBJ, 
             typename T1>
   static EventId ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1);
+
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -286,6 +313,7 @@
   template <typename MEM, typename OBJ, 
             typename T1, typename T2>
   static EventId ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1, T2 a2);
+
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -296,6 +324,7 @@
   template <typename MEM, typename OBJ, 
             typename T1, typename T2, typename T3>
   static EventId ScheduleNow (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3);
+
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -325,6 +354,7 @@
    * @param f the function to invoke
    */
   static EventId ScheduleNow (void (*f) (void));
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -332,6 +362,7 @@
   template <typename U1,
             typename T1>
   static EventId ScheduleNow (void (*f) (U1), T1 a1);
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -340,6 +371,7 @@
   template <typename U1, typename U2,
             typename T1, typename T2>
   static EventId ScheduleNow (void (*f) (U1,U2), T1 a1, T2 a2);
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -349,6 +381,7 @@
   template <typename U1, typename U2, typename U3,
             typename T1, typename T2, typename T3>
   static EventId ScheduleNow (void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3);
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -359,6 +392,7 @@
   template <typename U1, typename U2, typename U3, typename U4,
             typename T1, typename T2, typename T3, typename T4>
   static EventId ScheduleNow (void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4);
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -371,7 +405,6 @@
             typename T1, typename T2, typename T3, typename T4, typename T5>
   static EventId ScheduleNow (void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
 
-
   /**
    * Schedule an event to expire at Destroy time. All events 
    * scheduled to expire at "Destroy" time are scheduled FIFO, 
@@ -383,6 +416,7 @@
    */
   template <typename MEM, typename OBJ>
   static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj);
+
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -391,6 +425,7 @@
   template <typename MEM, typename OBJ, 
             typename T1>
   static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1);
+
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -400,6 +435,7 @@
   template <typename MEM, typename OBJ,
             typename T1, typename T2>
   static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1, T2 a2);
+
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -410,6 +446,7 @@
   template <typename MEM, typename OBJ, 
             typename T1, typename T2, typename T3>
   static EventId ScheduleDestroy (MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3);
+
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -439,6 +476,7 @@
    * @param f the function to invoke
    */
   static EventId ScheduleDestroy (void (*f) (void));
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -446,6 +484,7 @@
   template <typename U1,
             typename T1>
   static EventId ScheduleDestroy (void (*f) (U1), T1 a1);
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -454,6 +493,7 @@
   template <typename U1, typename U2,
             typename T1, typename T2>
   static EventId ScheduleDestroy (void (*f) (U1,U2), T1 a1, T2 a2);
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -463,6 +503,7 @@
   template <typename U1, typename U2, typename U3,
             typename T1, typename T2, typename T3>
   static EventId ScheduleDestroy (void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3);
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -473,6 +514,7 @@
   template <typename U1, typename U2, typename U3, typename U4,
             typename T1, typename T2, typename T3, typename T4>
   static EventId ScheduleDestroy (void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4);
+
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -497,6 +539,7 @@
    * @param id the event to remove from the list of scheduled events.
    */
   static void Remove (const EventId &id);
+
   /**
    * Set the cancel bit on this event: the event's associated function
    * will not be invoked when it expires. 
@@ -510,6 +553,7 @@
    * @param id the event to cancel
    */
   static void Cancel (const EventId &id);
+
   /**
    * This method has O(1) complexity.
    * Note that it is not possible to test for the expiration of
@@ -523,10 +567,12 @@
    * @returns true if the event has expired, false otherwise.
    */
   static bool IsExpired (const EventId &id);
+
   /**
    * Return the "current simulation time".
    */
   static Time Now (void);
+
   /**
    * \param id the event id to analyse
    * \returns the delay left until the input event id expires.
@@ -542,6 +588,7 @@
    * The returned value will always be bigger than or equal to Simulator::Now.
    */
   static Time GetMaximumSimulationTime (void);
+
   /**
    * \param time delay until the event expires
    * \param event the event to schedule
@@ -551,6 +598,7 @@
    * to delegate events to their own subclass of the EventImpl base class.
    */
   static EventId Schedule (Time const &time, const Ptr<EventImpl> &event);  
+
   /**
    * \param event the event to schedule
    * \returns a unique identifier for the newly-scheduled event.
@@ -559,6 +607,7 @@
    * to delegate events to their own subclass of the EventImpl base class.
    */
   static EventId ScheduleDestroy (const Ptr<EventImpl> &event);
+
   /**
    * \param event the event to schedule
    * \returns a unique identifier for the newly-scheduled event.
@@ -606,8 +655,10 @@
             typename T1, typename T2, typename T3, typename T4, typename T5>
   static Ptr<EventImpl> MakeEvent (void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
 
-  static Ptr<SimulatorImpl> GetImpl (void);
+  static SimulatorImpl *GetImpl (void);
   static Ptr<SimulatorImpl> m_impl;
+  static std::string m_typeImpl;
+  static std::string m_typeSched;
 };
 
 /**
--- a/src/simulator/wscript	Thu Jul 17 23:52:59 2008 -0700
+++ b/src/simulator/wscript	Fri Jul 18 21:51:31 2008 -0700
@@ -58,7 +58,7 @@
         'heap-scheduler.cc',
         'event-impl.cc',
         'simulator.cc',
-        'simulator-impl.cc',
+        'default-simulator-impl.cc',
         'timer.cc',
         'watchdog.cc',
         ]
@@ -72,6 +72,7 @@
         'event-impl.h',
         'simulator.h',
         'simulator-impl.h',
+        'default-simulator-impl.h',
         'scheduler.h',
         'list-scheduler.h',
         'map-scheduler.h',