1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2005,2006 INRIA
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;
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.
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
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
21 #include "simulator.h"
22 #include "default-simulator-impl.h"
23 #include "scheduler.h"
24 #include "event-impl.h"
27 #include "ns3/pointer.h"
28 #include "ns3/assert.h"
33 NS_LOG_COMPONENT_DEFINE ("DefaultSimulatorImpl");
37 NS_OBJECT_ENSURE_REGISTERED (DefaultSimulatorImpl);
40 DefaultSimulatorImpl::GetTypeId (void)
42 static TypeId tid = TypeId ("ns3::DefaultSimulatorImpl")
44 .AddConstructor<DefaultSimulatorImpl> ()
49 DefaultSimulatorImpl::DefaultSimulatorImpl ()
52 // uids are allocated from 4.
53 // uid 0 is "invalid" events
54 // uid 1 is "now" events
55 // uid 2 is "destroy" events
57 // before ::Run is entered, the m_currentUid will be zero
60 m_unscheduledEvents = 0;
63 DefaultSimulatorImpl::~DefaultSimulatorImpl ()
65 while (!m_events->IsEmpty ())
67 Scheduler::Event next = m_events->RemoveNext ();
74 DefaultSimulatorImpl::Destroy ()
76 while (!m_destroyEvents.empty ())
78 Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
79 m_destroyEvents.pop_front ();
80 NS_LOG_LOGIC ("handle destroy " << ev);
81 if (!ev->IsCancelled ())
89 DefaultSimulatorImpl::SetScheduler (ObjectFactory schedulerFactory)
91 Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
95 while (!m_events->IsEmpty ())
97 Scheduler::Event next = m_events->RemoveNext ();
98 scheduler->Insert (next);
101 m_events = scheduler;
105 DefaultSimulatorImpl::ProcessOneEvent (void)
107 Scheduler::Event next = m_events->RemoveNext ();
109 NS_ASSERT (next.key.m_ts >= m_currentTs);
110 --m_unscheduledEvents;
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 ();
120 DefaultSimulatorImpl::IsFinished (void) const
122 return m_events->IsEmpty () || m_stop;
126 DefaultSimulatorImpl::NextTs (void) const
128 NS_ASSERT (!m_events->IsEmpty ());
129 Scheduler::Event ev = m_events->PeekNext ();
134 DefaultSimulatorImpl::Next (void) const
136 return TimeStep (NextTs ());
140 DefaultSimulatorImpl::Run (void)
143 while (!m_events->IsEmpty () && !m_stop)
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);
154 DefaultSimulatorImpl::RunOneEvent (void)
160 DefaultSimulatorImpl::Stop (void)
167 // Schedule an event for a _relative_ time in the future.
170 DefaultSimulatorImpl::Schedule (Time const &time, EventImpl *event)
172 Time tAbsolute = time + Now();
174 NS_ASSERT (tAbsolute.IsPositive ());
175 NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
178 ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
179 ev.key.m_uid = m_uid;
181 ++m_unscheduledEvents;
182 m_events->Insert (ev);
183 return EventId (event, ev.key.m_ts, ev.key.m_uid);
187 DefaultSimulatorImpl::ScheduleNow (EventImpl *event)
191 ev.key.m_ts = m_currentTs;
192 ev.key.m_uid = m_uid;
194 ++m_unscheduledEvents;
195 m_events->Insert (ev);
196 return EventId (event, ev.key.m_ts, ev.key.m_uid);
200 DefaultSimulatorImpl::ScheduleDestroy (EventImpl *event)
202 EventId id (Ptr<EventImpl> (event, false), m_currentTs, 2);
203 m_destroyEvents.push_back (id);
209 DefaultSimulatorImpl::Now (void) const
211 return TimeStep (m_currentTs);
215 DefaultSimulatorImpl::GetDelayLeft (const EventId &id) const
223 return TimeStep (id.GetTs () - m_currentTs);
228 DefaultSimulatorImpl::Remove (const EventId &id)
230 if (id.GetUid () == 2)
233 for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
237 m_destroyEvents.erase (i);
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 ();
256 --m_unscheduledEvents;
260 DefaultSimulatorImpl::Cancel (const EventId &id)
264 id.PeekEventImpl ()->Cancel ();
269 DefaultSimulatorImpl::IsExpired (const EventId &ev) const
271 if (ev.GetUid () == 2)
273 if (ev.PeekEventImpl () == 0 ||
274 ev.PeekEventImpl ()->IsCancelled ())
279 for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
288 if (ev.PeekEventImpl () == 0 ||
289 ev.GetTs () < m_currentTs ||
290 (ev.GetTs () == m_currentTs &&
291 ev.GetUid () <= m_currentUid) ||
292 ev.PeekEventImpl ()->IsCancelled ())
303 DefaultSimulatorImpl::GetMaximumSimulationTime (void) const
305 // XXX: I am fairly certain other compilers use other non-standard
306 // post-fixes to indicate 64 bit constants.
307 return TimeStep (0x7fffffffffffffffLL);