A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
default-simulator-impl.cc
Go to the documentation of this file.
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 "ptr.h"
27 #include "pointer.h"
28 #include "assert.h"
29 #include "log.h"
30 
31 #include <cmath>
32 
33 // Note: Logging in this file is largely avoided due to the
34 // number of calls that are made to these functions and the possibility
35 // of causing recursions leading to stack overflow
36 
37 NS_LOG_COMPONENT_DEFINE ("DefaultSimulatorImpl");
38 
39 namespace ns3 {
40 
41 NS_OBJECT_ENSURE_REGISTERED (DefaultSimulatorImpl)
42  ;
43 
44 TypeId
46 {
47  static TypeId tid = TypeId ("ns3::DefaultSimulatorImpl")
49  .AddConstructor<DefaultSimulatorImpl> ()
50  ;
51  return tid;
52 }
53 
55 {
56  NS_LOG_FUNCTION (this);
57  m_stop = false;
58  // uids are allocated from 4.
59  // uid 0 is "invalid" events
60  // uid 1 is "now" events
61  // uid 2 is "destroy" events
62  m_uid = 4;
63  // before ::Run is entered, the m_currentUid will be zero
64  m_currentUid = 0;
65  m_currentTs = 0;
66  m_currentContext = 0xffffffff;
70 }
71 
73 {
74  NS_LOG_FUNCTION (this);
75 }
76 
77 void
79 {
80  NS_LOG_FUNCTION (this);
81  while (!m_events->IsEmpty ())
82  {
83  Scheduler::Event next = m_events->RemoveNext ();
84  next.impl->Unref ();
85  }
86  m_events = 0;
88 }
89 void
91 {
92  NS_LOG_FUNCTION (this);
93  while (!m_destroyEvents.empty ())
94  {
95  Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
96  m_destroyEvents.pop_front ();
97  NS_LOG_LOGIC ("handle destroy " << ev);
98  if (!ev->IsCancelled ())
99  {
100  ev->Invoke ();
101  }
102  }
103 }
104 
105 void
107 {
108  NS_LOG_FUNCTION (this << schedulerFactory);
109  Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
110 
111  if (m_events != 0)
112  {
113  while (!m_events->IsEmpty ())
114  {
115  Scheduler::Event next = m_events->RemoveNext ();
116  scheduler->Insert (next);
117  }
118  }
119  m_events = scheduler;
120 }
121 
122 // System ID for non-distributed simulation is always zero
123 uint32_t
125 {
126  return 0;
127 }
128 
129 void
131 {
132  Scheduler::Event next = m_events->RemoveNext ();
133 
134  NS_ASSERT (next.key.m_ts >= m_currentTs);
136 
137  NS_LOG_LOGIC ("handle " << next.key.m_ts);
138  m_currentTs = next.key.m_ts;
140  m_currentUid = next.key.m_uid;
141  next.impl->Invoke ();
142  next.impl->Unref ();
143 
145 }
146 
147 bool
149 {
150  return m_events->IsEmpty () || m_stop;
151 }
152 
153 void
155 {
157  {
158  return;
159  }
160 
161  // swap queues
162  EventsWithContext eventsWithContext;
163  {
165  m_eventsWithContext.swap(eventsWithContext);
167  }
168  while (!eventsWithContext.empty ())
169  {
170  EventWithContext event = eventsWithContext.front ();
171  eventsWithContext.pop_front ();
172  Scheduler::Event ev;
173  ev.impl = event.event;
174  ev.key.m_ts = m_currentTs + event.timestamp;
175  ev.key.m_context = event.context;
176  ev.key.m_uid = m_uid;
177  m_uid++;
179  m_events->Insert (ev);
180  }
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION (this);
187  // Set the current threadId as the main threadId
190  m_stop = false;
191 
192  while (!m_events->IsEmpty () && !m_stop)
193  {
194  ProcessOneEvent ();
195  }
196 
197  // If the simulator stopped naturally by lack of events, make a
198  // consistency test to check that we didn't lose any events along the way.
199  NS_ASSERT (!m_events->IsEmpty () || m_unscheduledEvents == 0);
200 }
201 
202 void
204 {
205  NS_LOG_FUNCTION (this);
206  m_stop = true;
207 }
208 
209 void
211 {
212  NS_LOG_FUNCTION (this << time.GetTimeStep ());
214 }
215 
216 //
217 // Schedule an event for a _relative_ time in the future.
218 //
219 EventId
221 {
222  NS_LOG_FUNCTION (this << time.GetTimeStep () << event);
223  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::Schedule Thread-unsafe invocation!");
224 
225  Time tAbsolute = time + TimeStep (m_currentTs);
226 
227  NS_ASSERT (tAbsolute.IsPositive ());
228  NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
229  Scheduler::Event ev;
230  ev.impl = event;
231  ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
232  ev.key.m_context = GetContext ();
233  ev.key.m_uid = m_uid;
234  m_uid++;
236  m_events->Insert (ev);
237  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
238 }
239 
240 void
241 DefaultSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event)
242 {
243  NS_LOG_FUNCTION (this << context << time.GetTimeStep () << event);
244 
246  {
247  Time tAbsolute = time + TimeStep (m_currentTs);
248  Scheduler::Event ev;
249  ev.impl = event;
250  ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
251  ev.key.m_context = context;
252  ev.key.m_uid = m_uid;
253  m_uid++;
255  m_events->Insert (ev);
256  }
257  else
258  {
259  EventWithContext ev;
260  ev.context = context;
261  ev.timestamp = time.GetTimeStep ();
262  ev.event = event;
263  {
265  m_eventsWithContext.push_back(ev);
266  m_eventsWithContextEmpty = false;
267  }
268  }
269 }
270 
271 EventId
273 {
274  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::ScheduleNow Thread-unsafe invocation!");
275 
276  Scheduler::Event ev;
277  ev.impl = event;
278  ev.key.m_ts = m_currentTs;
279  ev.key.m_context = GetContext ();
280  ev.key.m_uid = m_uid;
281  m_uid++;
283  m_events->Insert (ev);
284  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
285 }
286 
287 EventId
289 {
290  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::ScheduleDestroy Thread-unsafe invocation!");
291 
292  EventId id (Ptr<EventImpl> (event, false), m_currentTs, 0xffffffff, 2);
293  m_destroyEvents.push_back (id);
294  m_uid++;
295  return id;
296 }
297 
298 Time
300 {
301  // Do not add function logging here, to avoid stack overflow
302  return TimeStep (m_currentTs);
303 }
304 
305 Time
307 {
308  if (IsExpired (id))
309  {
310  return TimeStep (0);
311  }
312  else
313  {
314  return TimeStep (id.GetTs () - m_currentTs);
315  }
316 }
317 
318 void
320 {
321  if (id.GetUid () == 2)
322  {
323  // destroy events.
324  for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
325  {
326  if (*i == id)
327  {
328  m_destroyEvents.erase (i);
329  break;
330  }
331  }
332  return;
333  }
334  if (IsExpired (id))
335  {
336  return;
337  }
338  Scheduler::Event event;
339  event.impl = id.PeekEventImpl ();
340  event.key.m_ts = id.GetTs ();
341  event.key.m_context = id.GetContext ();
342  event.key.m_uid = id.GetUid ();
343  m_events->Remove (event);
344  event.impl->Cancel ();
345  // whenever we remove an event from the event list, we have to unref it.
346  event.impl->Unref ();
347 
349 }
350 
351 void
353 {
354  if (!IsExpired (id))
355  {
356  id.PeekEventImpl ()->Cancel ();
357  }
358 }
359 
360 bool
362 {
363  if (ev.GetUid () == 2)
364  {
365  if (ev.PeekEventImpl () == 0 ||
366  ev.PeekEventImpl ()->IsCancelled ())
367  {
368  return true;
369  }
370  // destroy events.
371  for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
372  {
373  if (*i == ev)
374  {
375  return false;
376  }
377  }
378  return true;
379  }
380  if (ev.PeekEventImpl () == 0 ||
381  ev.GetTs () < m_currentTs ||
382  (ev.GetTs () == m_currentTs &&
383  ev.GetUid () <= m_currentUid) ||
384  ev.PeekEventImpl ()->IsCancelled ())
385  {
386  return true;
387  }
388  else
389  {
390  return false;
391  }
392 }
393 
394 Time
396 {
399  return TimeStep (0x7fffffffffffffffLL);
400 }
401 
402 uint32_t
404 {
405  return m_currentContext;
406 }
407 
408 } // namespace ns3
keep track of time values and allow control of global simulation resolution
Definition: nstime.h:81
EventsWithContext m_eventsWithContext
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
bool IsPositive(void) const
Definition: nstime.h:244
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Time TimeStep(uint64_t ts)
Definition: nstime.h:950
virtual Time GetMaximumSimulationTime(void) const
virtual void SetScheduler(ObjectFactory schedulerFactory)
EventImpl * impl
Definition: scheduler.h:72
#define NS_ASSERT(condition)
Definition: assert.h:64
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
bool IsCancelled(void)
Definition: event-impl.cc:57
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:336
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:824
EventImpl * PeekEventImpl(void) const
Definition: event-id.cc:65
virtual EventId ScheduleNow(EventImpl *event)
virtual uint32_t GetSystemId(void) const
void Invoke(void)
Called by the simulation engine to notify the event that it has expired.
Definition: event-impl.cc:40
virtual void Remove(const EventId &ev)
Remove an event from the event list.
Ptr< Object > Create(void) const
A class which provides a simple way to implement a Critical Section.
Definition: system-mutex.h:109
virtual Time Now(void) const
Return the "current simulation time".
void Unref(void) const
Decrement the reference count.
uint32_t GetUid(void) const
Definition: event-id.cc:83
Maintain the event list.
Definition: scheduler.h:57
#define NS_LOG_LOGIC(msg)
Definition: log.h:368
virtual bool IsExpired(const EventId &ev) const
This method has O(1) complexity.
virtual Time GetDelayLeft(const EventId &id) const
virtual EventId ScheduleDestroy(EventImpl *event)
std::list< struct EventWithContext > EventsWithContext
static bool Equals(ThreadId id)
Compares an TharedId with the current ThreadId .
virtual void Cancel(const EventId &ev)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
virtual void Stop(void)
If an event invokes this method, it will be the last event scheduled by the Simulator::Run method bef...
virtual uint32_t GetContext(void) const
int64_t GetTimeStep(void) const
Definition: nstime.h:356
virtual void ScheduleWithContext(uint32_t context, Time const &time, EventImpl *event)
NS_LOG_COMPONENT_DEFINE("DefaultSimulatorImpl")
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
virtual EventId Schedule(Time const &time, EventImpl *event)
instantiate subclasses of ns3::Object.
a simulation event
Definition: event-impl.h:39
virtual bool IsFinished(void) const
If there are no more events lefts to be scheduled, or if simulation time has already reached the "sto...
virtual void Run(void)
Run the simulation until one of:
an identifier for simulation events.
Definition: event-id.h:46
static void Stop(void)
If an event invokes this method, it will be the last event scheduled by the Simulator::run method bef...
Definition: simulator.cc:165
virtual void Destroy()
This method is typically invoked at the end of a simulation to avoid false-positive reports by a leak...
SystemThread::ThreadId m_main
static ThreadId Self(void)
Returns the current thread Id.
a unique identifier for an interface.
Definition: type-id.h:49
TypeId SetParent(TypeId tid)
Definition: type-id.cc:611
uint64_t GetTs(void) const
Definition: event-id.cc:71
Doxygen introspection did not find any typical Config paths.