author | Craig Dowell <craigdo@ee.washington.edu> |
Fri, 18 Jul 2008 21:51:31 -0700 | |
changeset 3470 | 21022872009d |
parent 3469 | 9e763021e045 |
child 3471 | 0896bd4a38dd |
--- /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',