src/simulator/default-simulator-impl.cc
author Guillaume Seguin <guillaume@segu.in>
Thu Nov 12 13:19:35 2009 +0100 (2009-11-12)
changeset 5507 915abd2b907b
parent 5302 5ed72d440db4
child 5521 37c6c83d4252
permissions -rw-r--r--
Simulator::SetScheduler now takes an ObjectFactory
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2005,2006 INRIA
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    19  */
    20 
    21 #include "simulator.h"
    22 #include "default-simulator-impl.h"
    23 #include "scheduler.h"
    24 #include "event-impl.h"
    25 
    26 #include "ns3/ptr.h"
    27 #include "ns3/pointer.h"
    28 #include "ns3/assert.h"
    29 #include "ns3/log.h"
    30 
    31 #include <math.h>
    32 
    33 NS_LOG_COMPONENT_DEFINE ("DefaultSimulatorImpl");
    34 
    35 namespace ns3 {
    36 
    37 NS_OBJECT_ENSURE_REGISTERED (DefaultSimulatorImpl);
    38 
    39 TypeId
    40 DefaultSimulatorImpl::GetTypeId (void)
    41 {
    42   static TypeId tid = TypeId ("ns3::DefaultSimulatorImpl")
    43     .SetParent<Object> ()
    44     .AddConstructor<DefaultSimulatorImpl> ()
    45     ;
    46   return tid;
    47 }
    48 
    49 DefaultSimulatorImpl::DefaultSimulatorImpl ()
    50 {
    51   m_stop = false;
    52   // uids are allocated from 4.
    53   // uid 0 is "invalid" events
    54   // uid 1 is "now" events
    55   // uid 2 is "destroy" events
    56   m_uid = 4; 
    57   // before ::Run is entered, the m_currentUid will be zero
    58   m_currentUid = 0;
    59   m_currentTs = 0;
    60   m_unscheduledEvents = 0;
    61 }
    62 
    63 DefaultSimulatorImpl::~DefaultSimulatorImpl ()
    64 {
    65   while (!m_events->IsEmpty ())
    66     {
    67       Scheduler::Event next = m_events->RemoveNext ();
    68       next.impl->Unref ();
    69     }
    70   m_events = 0;
    71 }
    72 
    73 void
    74 DefaultSimulatorImpl::Destroy ()
    75 {
    76   while (!m_destroyEvents.empty ()) 
    77     {
    78       Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
    79       m_destroyEvents.pop_front ();
    80       NS_LOG_LOGIC ("handle destroy " << ev);
    81       if (!ev->IsCancelled ())
    82         {
    83           ev->Invoke ();
    84         }
    85     }
    86 }
    87 
    88 void
    89 DefaultSimulatorImpl::SetScheduler (ObjectFactory schedulerFactory)
    90 {
    91   Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
    92 
    93   if (m_events != 0)
    94     {
    95       while (!m_events->IsEmpty ())
    96         {
    97           Scheduler::Event next = m_events->RemoveNext ();
    98           scheduler->Insert (next);
    99         }
   100     }
   101   m_events = scheduler;
   102 }
   103 
   104 void
   105 DefaultSimulatorImpl::ProcessOneEvent (void)
   106 {
   107   Scheduler::Event next = m_events->RemoveNext ();
   108 
   109   NS_ASSERT (next.key.m_ts >= m_currentTs);
   110   --m_unscheduledEvents;
   111 
   112   NS_LOG_LOGIC ("handle " << next.key.m_ts);
   113   m_currentTs = next.key.m_ts;
   114   m_currentUid = next.key.m_uid;
   115   next.impl->Invoke ();
   116   next.impl->Unref ();
   117 }
   118 
   119 bool 
   120 DefaultSimulatorImpl::IsFinished (void) const
   121 {
   122   return m_events->IsEmpty () || m_stop;
   123 }
   124 
   125 uint64_t
   126 DefaultSimulatorImpl::NextTs (void) const
   127 {
   128   NS_ASSERT (!m_events->IsEmpty ());
   129   Scheduler::Event ev = m_events->PeekNext ();
   130   return ev.key.m_ts;
   131 }
   132 
   133 Time
   134 DefaultSimulatorImpl::Next (void) const
   135 {
   136   return TimeStep (NextTs ());
   137 }
   138 
   139 void
   140 DefaultSimulatorImpl::Run (void)
   141 {
   142   m_stop = false;
   143   while (!m_events->IsEmpty () && !m_stop) 
   144     {
   145       ProcessOneEvent ();
   146     }
   147 
   148   // If the simulator stopped naturally by lack of events, make a
   149   // consistency test to check that we didn't lose any events along the way.
   150   NS_ASSERT(!m_events->IsEmpty () || m_unscheduledEvents == 0);
   151 }
   152 
   153 void
   154 DefaultSimulatorImpl::RunOneEvent (void)
   155 {
   156   ProcessOneEvent ();
   157 }
   158 
   159 void 
   160 DefaultSimulatorImpl::Stop (void)
   161 {
   162   m_stop = true;
   163 }
   164 
   165 
   166 //
   167 // Schedule an event for a _relative_ time in the future.
   168 //
   169 EventId
   170 DefaultSimulatorImpl::Schedule (Time const &time, EventImpl *event)
   171 {
   172   Time tAbsolute = time + Now();
   173 
   174   NS_ASSERT (tAbsolute.IsPositive ());
   175   NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
   176   Scheduler::Event ev;
   177   ev.impl = event;
   178   ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
   179   ev.key.m_uid = m_uid;
   180   m_uid++;
   181   ++m_unscheduledEvents;
   182   m_events->Insert (ev);
   183   return EventId (event, ev.key.m_ts, ev.key.m_uid);
   184 }
   185 
   186 EventId
   187 DefaultSimulatorImpl::ScheduleNow (EventImpl *event)
   188 {
   189   Scheduler::Event ev;
   190   ev.impl = event;
   191   ev.key.m_ts = m_currentTs;
   192   ev.key.m_uid = m_uid;
   193   m_uid++;
   194   ++m_unscheduledEvents;
   195   m_events->Insert (ev);
   196   return EventId (event, ev.key.m_ts, ev.key.m_uid);
   197 }
   198 
   199 EventId
   200 DefaultSimulatorImpl::ScheduleDestroy (EventImpl *event)
   201 {
   202   EventId id (Ptr<EventImpl> (event, false), m_currentTs, 2);
   203   m_destroyEvents.push_back (id);
   204   m_uid++;
   205   return id;
   206 }
   207 
   208 Time
   209 DefaultSimulatorImpl::Now (void) const
   210 {
   211   return TimeStep (m_currentTs);
   212 }
   213 
   214 Time 
   215 DefaultSimulatorImpl::GetDelayLeft (const EventId &id) const
   216 {
   217   if (IsExpired (id))
   218     {
   219       return TimeStep (0);
   220     }
   221   else
   222     {
   223       return TimeStep (id.GetTs () - m_currentTs);
   224     }
   225 }
   226 
   227 void
   228 DefaultSimulatorImpl::Remove (const EventId &id)
   229 {
   230   if (id.GetUid () == 2)
   231     {
   232       // destroy events.
   233       for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
   234         {
   235           if (*i == id)
   236             {
   237               m_destroyEvents.erase (i);
   238               break;
   239             }
   240          }
   241       return;
   242     }
   243   if (IsExpired (id))
   244     {
   245       return;
   246     }
   247   Scheduler::Event event;
   248   event.impl = id.PeekEventImpl ();
   249   event.key.m_ts = id.GetTs ();
   250   event.key.m_uid = id.GetUid ();
   251   m_events->Remove (event);
   252   event.impl->Cancel ();
   253   // whenever we remove an event from the event list, we have to unref it.
   254   event.impl->Unref ();
   255 
   256   --m_unscheduledEvents;
   257 }
   258 
   259 void
   260 DefaultSimulatorImpl::Cancel (const EventId &id)
   261 {
   262   if (!IsExpired (id))
   263     {
   264       id.PeekEventImpl ()->Cancel ();
   265     }
   266 }
   267 
   268 bool
   269 DefaultSimulatorImpl::IsExpired (const EventId &ev) const
   270 {
   271   if (ev.GetUid () == 2)
   272     {
   273       if (ev.PeekEventImpl () == 0 ||
   274           ev.PeekEventImpl ()->IsCancelled ())
   275         {
   276           return true;
   277         }
   278       // destroy events.
   279       for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
   280         {
   281           if (*i == ev)
   282             {
   283               return false;
   284             }
   285          }
   286       return true;
   287     }
   288   if (ev.PeekEventImpl () == 0 ||
   289       ev.GetTs () < m_currentTs ||
   290       (ev.GetTs () == m_currentTs &&
   291        ev.GetUid () <= m_currentUid) ||
   292       ev.PeekEventImpl ()->IsCancelled ()) 
   293     {
   294       return true;
   295     }
   296   else
   297     {
   298       return false;
   299     }
   300 }
   301 
   302 Time 
   303 DefaultSimulatorImpl::GetMaximumSimulationTime (void) const
   304 {
   305   // XXX: I am fairly certain other compilers use other non-standard
   306   // post-fixes to indicate 64 bit constants.
   307   return TimeStep (0x7fffffffffffffffLL);
   308 }
   309 
   310 } // namespace ns3
   311 
   312