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&#39;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)
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:171
bool IsCancelled(void)
Definition: event-impl.cc:57
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object&#39;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 &quot;time&quot; 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 &quot;current simulation time&quot;.
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&#39;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)
#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 &quot;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.