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 TypeId
45 {
46  static TypeId tid = TypeId ("ns3::DefaultSimulatorImpl")
48  .AddConstructor<DefaultSimulatorImpl> ()
49  ;
50  return tid;
51 }
52 
54 {
55  NS_LOG_FUNCTION (this);
56  m_stop = false;
57  // uids are allocated from 4.
58  // uid 0 is "invalid" events
59  // uid 1 is "now" events
60  // uid 2 is "destroy" events
61  m_uid = 4;
62  // before ::Run is entered, the m_currentUid will be zero
63  m_currentUid = 0;
64  m_currentTs = 0;
65  m_currentContext = 0xffffffff;
69 }
70 
72 {
73  NS_LOG_FUNCTION (this);
74 }
75 
76 void
78 {
79  NS_LOG_FUNCTION (this);
80  while (!m_events->IsEmpty ())
81  {
82  Scheduler::Event next = m_events->RemoveNext ();
83  next.impl->Unref ();
84  }
85  m_events = 0;
87 }
88 void
90 {
91  NS_LOG_FUNCTION (this);
92  while (!m_destroyEvents.empty ())
93  {
94  Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
95  m_destroyEvents.pop_front ();
96  NS_LOG_LOGIC ("handle destroy " << ev);
97  if (!ev->IsCancelled ())
98  {
99  ev->Invoke ();
100  }
101  }
102 }
103 
104 void
106 {
107  NS_LOG_FUNCTION (this << schedulerFactory);
108  Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
109 
110  if (m_events != 0)
111  {
112  while (!m_events->IsEmpty ())
113  {
114  Scheduler::Event next = m_events->RemoveNext ();
115  scheduler->Insert (next);
116  }
117  }
118  m_events = scheduler;
119 }
120 
121 // System ID for non-distributed simulation is always zero
122 uint32_t
124 {
125  return 0;
126 }
127 
128 void
130 {
131  Scheduler::Event next = m_events->RemoveNext ();
132 
133  NS_ASSERT (next.key.m_ts >= m_currentTs);
135 
136  NS_LOG_LOGIC ("handle " << next.key.m_ts);
137  m_currentTs = next.key.m_ts;
139  m_currentUid = next.key.m_uid;
140  next.impl->Invoke ();
141  next.impl->Unref ();
142 
144 }
145 
146 bool
148 {
149  return m_events->IsEmpty () || m_stop;
150 }
151 
152 void
154 {
156  {
157  return;
158  }
159 
160  // swap queues
161  EventsWithContext eventsWithContext;
162  {
164  m_eventsWithContext.swap(eventsWithContext);
166  }
167  while (!eventsWithContext.empty ())
168  {
169  EventWithContext event = eventsWithContext.front ();
170  eventsWithContext.pop_front ();
171  Scheduler::Event ev;
172  ev.impl = event.event;
173  ev.key.m_ts = m_currentTs + event.timestamp;
174  ev.key.m_context = event.context;
175  ev.key.m_uid = m_uid;
176  m_uid++;
178  m_events->Insert (ev);
179  }
180 }
181 
182 void
184 {
185  NS_LOG_FUNCTION (this);
186  // Set the current threadId as the main threadId
189  m_stop = false;
190 
191  while (!m_events->IsEmpty () && !m_stop)
192  {
193  ProcessOneEvent ();
194  }
195 
196  // If the simulator stopped naturally by lack of events, make a
197  // consistency test to check that we didn't lose any events along the way.
198  NS_ASSERT (!m_events->IsEmpty () || m_unscheduledEvents == 0);
199 }
200 
201 void
203 {
204  NS_LOG_FUNCTION (this);
205  m_stop = true;
206 }
207 
208 void
210 {
211  NS_LOG_FUNCTION (this << time.GetTimeStep ());
213 }
214 
215 //
216 // Schedule an event for a _relative_ time in the future.
217 //
218 EventId
220 {
221  NS_LOG_FUNCTION (this << time.GetTimeStep () << event);
222  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::Schedule Thread-unsafe invocation!");
223 
224  Time tAbsolute = time + TimeStep (m_currentTs);
225 
226  NS_ASSERT (tAbsolute.IsPositive ());
227  NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
228  Scheduler::Event ev;
229  ev.impl = event;
230  ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
231  ev.key.m_context = GetContext ();
232  ev.key.m_uid = m_uid;
233  m_uid++;
235  m_events->Insert (ev);
236  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
237 }
238 
239 void
240 DefaultSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event)
241 {
242  NS_LOG_FUNCTION (this << context << time.GetTimeStep () << event);
243 
245  {
246  Time tAbsolute = time + TimeStep (m_currentTs);
247  Scheduler::Event ev;
248  ev.impl = event;
249  ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
250  ev.key.m_context = context;
251  ev.key.m_uid = m_uid;
252  m_uid++;
254  m_events->Insert (ev);
255  }
256  else
257  {
258  EventWithContext ev;
259  ev.context = context;
260  ev.timestamp = time.GetTimeStep ();
261  ev.event = event;
262  {
264  m_eventsWithContext.push_back(ev);
265  m_eventsWithContextEmpty = false;
266  }
267  }
268 }
269 
270 EventId
272 {
273  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::ScheduleNow Thread-unsafe invocation!");
274 
275  Scheduler::Event ev;
276  ev.impl = event;
277  ev.key.m_ts = m_currentTs;
278  ev.key.m_context = GetContext ();
279  ev.key.m_uid = m_uid;
280  m_uid++;
282  m_events->Insert (ev);
283  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
284 }
285 
286 EventId
288 {
289  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::ScheduleDestroy Thread-unsafe invocation!");
290 
291  EventId id (Ptr<EventImpl> (event, false), m_currentTs, 0xffffffff, 2);
292  m_destroyEvents.push_back (id);
293  m_uid++;
294  return id;
295 }
296 
297 Time
299 {
300  // Do not add function logging here, to avoid stack overflow
301  return TimeStep (m_currentTs);
302 }
303 
304 Time
306 {
307  if (IsExpired (id))
308  {
309  return TimeStep (0);
310  }
311  else
312  {
313  return TimeStep (id.GetTs () - m_currentTs);
314  }
315 }
316 
317 void
319 {
320  if (id.GetUid () == 2)
321  {
322  // destroy events.
323  for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
324  {
325  if (*i == id)
326  {
327  m_destroyEvents.erase (i);
328  break;
329  }
330  }
331  return;
332  }
333  if (IsExpired (id))
334  {
335  return;
336  }
337  Scheduler::Event event;
338  event.impl = id.PeekEventImpl ();
339  event.key.m_ts = id.GetTs ();
340  event.key.m_context = id.GetContext ();
341  event.key.m_uid = id.GetUid ();
342  m_events->Remove (event);
343  event.impl->Cancel ();
344  // whenever we remove an event from the event list, we have to unref it.
345  event.impl->Unref ();
346 
348 }
349 
350 void
352 {
353  if (!IsExpired (id))
354  {
355  id.PeekEventImpl ()->Cancel ();
356  }
357 }
358 
359 bool
361 {
362  if (ev.GetUid () == 2)
363  {
364  if (ev.PeekEventImpl () == 0 ||
365  ev.PeekEventImpl ()->IsCancelled ())
366  {
367  return true;
368  }
369  // destroy events.
370  for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
371  {
372  if (*i == ev)
373  {
374  return false;
375  }
376  }
377  return true;
378  }
379  if (ev.PeekEventImpl () == 0 ||
380  ev.GetTs () < m_currentTs ||
381  (ev.GetTs () == m_currentTs &&
382  ev.GetUid () <= m_currentUid) ||
383  ev.PeekEventImpl ()->IsCancelled ())
384  {
385  return true;
386  }
387  else
388  {
389  return false;
390  }
391 }
392 
393 Time
395 {
398  return TimeStep (0x7fffffffffffffffLL);
399 }
400 
401 uint32_t
403 {
404  return m_currentContext;
405 }
406 
407 } // namespace ns3
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
EventsWithContext m_eventsWithContext
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:60
bool IsPositive(void) const
Definition: nstime.h:242
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
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:997
virtual Time GetMaximumSimulationTime(void) const
virtual void SetScheduler(ObjectFactory schedulerFactory)
static ThreadId Self(void)
Returns the current thread Id.
EventImpl * impl
Definition: scheduler.h:73
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
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:335
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:825
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:58
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
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
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:354
virtual void ScheduleWithContext(uint32_t context, Time const &time, EventImpl *event)
static bool Equals(ThreadId id)
Compares an TharedId with the current ThreadId .
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:84
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
a unique identifier for an interface.
Definition: type-id.h:49
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
uint64_t GetTs(void) const
Definition: event-id.cc:71
Doxygen introspection did not find any typical Config paths.