A Discrete-Event Network Simulator
API
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 
40 namespace ns3 {
41 
42 // Note: Logging in this file is largely avoided due to the
43 // number of calls that are made to these functions and the possibility
44 // of causing recursions leading to stack overflow
45 NS_LOG_COMPONENT_DEFINE ("DefaultSimulatorImpl");
46 
47 NS_OBJECT_ENSURE_REGISTERED (DefaultSimulatorImpl);
48 
49 TypeId
51 {
52  static TypeId tid = TypeId ("ns3::DefaultSimulatorImpl")
54  .SetGroupName ("Core")
55  .AddConstructor<DefaultSimulatorImpl> ()
56  ;
57  return tid;
58 }
59 
61 {
62  NS_LOG_FUNCTION (this);
63  m_stop = false;
64  // uids are allocated from 4.
65  // uid 0 is "invalid" events
66  // uid 1 is "now" events
67  // uid 2 is "destroy" events
68  m_uid = 4;
69  // before ::Run is entered, the m_currentUid will be zero
70  m_currentUid = 0;
71  m_currentTs = 0;
74  m_eventCount = 0;
77 }
78 
80 {
81  NS_LOG_FUNCTION (this);
82 }
83 
84 void
86 {
87  NS_LOG_FUNCTION (this);
89 
90  while (!m_events->IsEmpty ())
91  {
92  Scheduler::Event next = m_events->RemoveNext ();
93  next.impl->Unref ();
94  }
95  m_events = 0;
97 }
98 void
100 {
101  NS_LOG_FUNCTION (this);
102  while (!m_destroyEvents.empty ())
103  {
104  Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
105  m_destroyEvents.pop_front ();
106  NS_LOG_LOGIC ("handle destroy " << ev);
107  if (!ev->IsCancelled ())
108  {
109  ev->Invoke ();
110  }
111  }
112 }
113 
114 void
116 {
117  NS_LOG_FUNCTION (this << schedulerFactory);
118  Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
119 
120  if (m_events != 0)
121  {
122  while (!m_events->IsEmpty ())
123  {
124  Scheduler::Event next = m_events->RemoveNext ();
125  scheduler->Insert (next);
126  }
127  }
128  m_events = scheduler;
129 }
130 
131 // System ID for non-distributed simulation is always zero
132 uint32_t
134 {
135  return 0;
136 }
137 
138 void
140 {
141  Scheduler::Event next = m_events->RemoveNext ();
142 
143  NS_ASSERT (next.key.m_ts >= m_currentTs);
145  m_eventCount++;
146 
147  NS_LOG_LOGIC ("handle " << next.key.m_ts);
148  m_currentTs = next.key.m_ts;
150  m_currentUid = next.key.m_uid;
151  next.impl->Invoke ();
152  next.impl->Unref ();
153 
155 }
156 
157 bool
159 {
160  return m_events->IsEmpty () || m_stop;
161 }
162 
163 void
165 {
167  {
168  return;
169  }
170 
171  // swap queues
172  EventsWithContext eventsWithContext;
173  {
175  m_eventsWithContext.swap (eventsWithContext);
177  }
178  while (!eventsWithContext.empty ())
179  {
180  EventWithContext event = eventsWithContext.front ();
181  eventsWithContext.pop_front ();
182  Scheduler::Event ev;
183  ev.impl = event.event;
184  ev.key.m_ts = m_currentTs + event.timestamp;
185  ev.key.m_context = event.context;
186  ev.key.m_uid = m_uid;
187  m_uid++;
189  m_events->Insert (ev);
190  }
191 }
192 
193 void
195 {
196  NS_LOG_FUNCTION (this);
197  // Set the current threadId as the main threadId
200  m_stop = false;
201 
202  while (!m_events->IsEmpty () && !m_stop)
203  {
204  ProcessOneEvent ();
205  }
206 
207  // If the simulator stopped naturally by lack of events, make a
208  // consistency test to check that we didn't lose any events along the way.
209  NS_ASSERT (!m_events->IsEmpty () || m_unscheduledEvents == 0);
210 }
211 
212 void
214 {
215  NS_LOG_FUNCTION (this);
216  m_stop = true;
217 }
218 
219 void
221 {
222  NS_LOG_FUNCTION (this << delay.GetTimeStep ());
224 }
225 
226 //
227 // Schedule an event for a _relative_ time in the future.
228 //
229 EventId
231 {
232  NS_LOG_FUNCTION (this << delay.GetTimeStep () << event);
233  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::Schedule Thread-unsafe invocation!");
234 
235  NS_ASSERT_MSG (delay.IsPositive (), "DefaultSimulatorImpl::Schedule(): Negative delay");
236  Time tAbsolute = delay + TimeStep (m_currentTs);
237 
238  Scheduler::Event ev;
239  ev.impl = event;
240  ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
241  ev.key.m_context = GetContext ();
242  ev.key.m_uid = m_uid;
243  m_uid++;
245  m_events->Insert (ev);
246  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
247 }
248 
249 void
250 DefaultSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &delay, EventImpl *event)
251 {
252  NS_LOG_FUNCTION (this << context << delay.GetTimeStep () << event);
253 
255  {
256  Time tAbsolute = delay + TimeStep (m_currentTs);
257  Scheduler::Event ev;
258  ev.impl = event;
259  ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
260  ev.key.m_context = context;
261  ev.key.m_uid = m_uid;
262  m_uid++;
264  m_events->Insert (ev);
265  }
266  else
267  {
268  EventWithContext ev;
269  ev.context = context;
270  // Current time added in ProcessEventsWithContext()
271  ev.timestamp = delay.GetTimeStep ();
272  ev.event = event;
273  {
275  m_eventsWithContext.push_back (ev);
276  m_eventsWithContextEmpty = false;
277  }
278  }
279 }
280 
281 EventId
283 {
284  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::ScheduleNow Thread-unsafe invocation!");
285 
286  Scheduler::Event ev;
287  ev.impl = event;
288  ev.key.m_ts = m_currentTs;
289  ev.key.m_context = GetContext ();
290  ev.key.m_uid = m_uid;
291  m_uid++;
293  m_events->Insert (ev);
294  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
295 }
296 
297 EventId
299 {
300  NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::ScheduleDestroy Thread-unsafe invocation!");
301 
302  EventId id (Ptr<EventImpl> (event, false), m_currentTs, 0xffffffff, 2);
303  m_destroyEvents.push_back (id);
304  m_uid++;
305  return id;
306 }
307 
308 Time
310 {
311  // Do not add function logging here, to avoid stack overflow
312  return TimeStep (m_currentTs);
313 }
314 
315 Time
317 {
318  if (IsExpired (id))
319  {
320  return TimeStep (0);
321  }
322  else
323  {
324  return TimeStep (id.GetTs () - m_currentTs);
325  }
326 }
327 
328 void
330 {
331  if (id.GetUid () == 2)
332  {
333  // destroy events.
334  for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
335  {
336  if (*i == id)
337  {
338  m_destroyEvents.erase (i);
339  break;
340  }
341  }
342  return;
343  }
344  if (IsExpired (id))
345  {
346  return;
347  }
348  Scheduler::Event event;
349  event.impl = id.PeekEventImpl ();
350  event.key.m_ts = id.GetTs ();
351  event.key.m_context = id.GetContext ();
352  event.key.m_uid = id.GetUid ();
353  m_events->Remove (event);
354  event.impl->Cancel ();
355  // whenever we remove an event from the event list, we have to unref it.
356  event.impl->Unref ();
357 
359 }
360 
361 void
363 {
364  if (!IsExpired (id))
365  {
366  id.PeekEventImpl ()->Cancel ();
367  }
368 }
369 
370 bool
372 {
373  if (id.GetUid () == 2)
374  {
375  if (id.PeekEventImpl () == 0
376  || id.PeekEventImpl ()->IsCancelled ())
377  {
378  return true;
379  }
380  // destroy events.
381  for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
382  {
383  if (*i == id)
384  {
385  return false;
386  }
387  }
388  return true;
389  }
390  if (id.PeekEventImpl () == 0
391  || id.GetTs () < m_currentTs
392  || (id.GetTs () == m_currentTs && id.GetUid () <= m_currentUid)
393  || id.PeekEventImpl ()->IsCancelled ())
394  {
395  return true;
396  }
397  else
398  {
399  return false;
400  }
401 }
402 
403 Time
405 {
406  return TimeStep (0x7fffffffffffffffLL);
407 }
408 
409 uint32_t
411 {
412  return m_currentContext;
413 }
414 
415 uint64_t
417 {
418  return m_eventCount;
419 }
420 
421 } // namespace ns3
ns3::DefaultSimulatorImpl::ScheduleNow
virtual EventId ScheduleNow(EventImpl *event)
Schedule an event to run at the current virtual time.
Definition: default-simulator-impl.cc:282
ns3::TypeId
a unique identifier for an interface.
Definition: type-id.h:59
NS_LOG_COMPONENT_DEFINE
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
NS_OBJECT_ENSURE_REGISTERED
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
NS_ASSERT
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
ns3::DefaultSimulatorImpl::ScheduleDestroy
virtual EventId ScheduleDestroy(EventImpl *event)
Schedule an event to run at the end of the simulation, after the Stop() time or condition has been re...
Definition: default-simulator-impl.cc:298
ns3::EventId
An identifier for simulation events.
Definition: event-id.h:54
ns3::DefaultSimulatorImpl::GetDelayLeft
virtual Time GetDelayLeft(const EventId &id) const
Get the remaining time until this event will execute.
Definition: default-simulator-impl.cc:316
ns3
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns3::DefaultSimulatorImpl::Stop
virtual void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: default-simulator-impl.cc:213
ns3::Scheduler::Event::impl
EventImpl * impl
Pointer to the event implementation.
Definition: scheduler.h:183
ns3::DefaultSimulatorImpl::GetTypeId
static TypeId GetTypeId(void)
Register this type.
Definition: default-simulator-impl.cc:50
ns3::DefaultSimulatorImpl::GetEventCount
virtual uint64_t GetEventCount(void) const
Get the number of events executed.
Definition: default-simulator-impl.cc:416
assert.h
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
ns3::DefaultSimulatorImpl::ProcessOneEvent
void ProcessOneEvent(void)
Process the next event.
Definition: default-simulator-impl.cc:139
ns3::Simulator::Schedule
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
ns3::DefaultSimulatorImpl::Cancel
virtual void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: default-simulator-impl.cc:362
ns3::TypeId::SetParent
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
scheduler.h
ns3::Scheduler abstract base class, ns3::Scheduler::Event and ns3::Scheduler::EventKey declarations.
ns3::DefaultSimulatorImpl::m_eventsWithContextEmpty
bool m_eventsWithContextEmpty
Flag true if all events with context have been moved to the primary event queue.
Definition: default-simulator-impl.h:108
ns3::Scheduler::EventKey::m_ts
uint64_t m_ts
Event time stamp.
Definition: scheduler.h:170
ns3::DefaultSimulatorImpl::m_main
SystemThread::ThreadId m_main
Main execution thread.
Definition: default-simulator-impl.h:138
ns3::DefaultSimulatorImpl::Schedule
virtual EventId Schedule(const Time &delay, EventImpl *event)
Schedule a future event execution (in the same context).
Definition: default-simulator-impl.cc:230
ns3::Time::GetTimeStep
int64_t GetTimeStep(void) const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:416
ns3::Scheduler::Event
Scheduler event.
Definition: scheduler.h:182
ns3::Ptr
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
ns3::DefaultSimulatorImpl::m_destroyEvents
DestroyEvents m_destroyEvents
The container of events to run at Destroy.
Definition: default-simulator-impl.h:115
ns3::DefaultSimulatorImpl
The default single process simulator implementation.
Definition: default-simulator-impl.h:48
ns3::DefaultSimulatorImpl::ProcessEventsWithContext
void ProcessEventsWithContext(void)
Move events from a different context into the main event queue.
Definition: default-simulator-impl.cc:164
ns3::DefaultSimulatorImpl::ScheduleWithContext
virtual void ScheduleWithContext(uint32_t context, const Time &delay, EventImpl *event)
Schedule a future event execution (in a different context).
Definition: default-simulator-impl.cc:250
ns3::Simulator::Stop
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
ns3::Scheduler::Event::key
EventKey key
Key for sorting and ordering Events.
Definition: scheduler.h:184
ns3::Scheduler::EventKey::m_context
uint32_t m_context
Event context.
Definition: scheduler.h:172
ns3::DefaultSimulatorImpl::DefaultSimulatorImpl
DefaultSimulatorImpl()
Constructor.
Definition: default-simulator-impl.cc:60
ns3::DefaultSimulatorImpl::m_currentTs
uint64_t m_currentTs
Timestamp of the current event.
Definition: default-simulator-impl.h:126
ns3::EventImpl::Invoke
void Invoke(void)
Called by the simulation engine to notify the event that it is time to execute.
Definition: event-impl.cc:46
pointer.h
ns3::PointerValue attribute value declarations and template implementations.
ns3::CriticalSection
A class which provides a simple way to implement a Critical Section.
Definition: system-mutex.h:119
ns3::ObjectFactory
Instantiate subclasses of ns3::Object.
Definition: object-factory.h:48
ns3::DefaultSimulatorImpl::Now
virtual Time Now(void) const
Return the current simulation virtual time.
Definition: default-simulator-impl.cc:309
ns3::DefaultSimulatorImpl::m_eventsWithContextMutex
SystemMutex m_eventsWithContextMutex
Mutex to control access to the list of events with context.
Definition: default-simulator-impl.h:110
event-impl.h
ns3::EventImpl declarations.
ns3::DefaultSimulatorImpl::Run
virtual void Run(void)
Run the simulation.
Definition: default-simulator-impl.cc:194
ns3::Time
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
ns3::DefaultSimulatorImpl::GetSystemId
virtual uint32_t GetSystemId(void) const
Get the system id of this simulator.
Definition: default-simulator-impl.cc:133
ns3::SimpleRefCount::Unref
void Unref(void) const
Decrement the reference count.
Definition: simple-ref-count.h:116
ns3::DefaultSimulatorImpl::m_unscheduledEvents
int m_unscheduledEvents
Number of events that have been inserted but not yet scheduled, not counting the Destroy events; this...
Definition: default-simulator-impl.h:135
ns3::DefaultSimulatorImpl::GetMaximumSimulationTime
virtual Time GetMaximumSimulationTime(void) const
Get the maximum representable simulation time.
Definition: default-simulator-impl.cc:404
NS_ASSERT_MSG
#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:88
ns3::DefaultSimulatorImpl::m_events
Ptr< Scheduler > m_events
The event priority queue.
Definition: default-simulator-impl.h:119
ns3::DefaultSimulatorImpl::Destroy
virtual void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: default-simulator-impl.cc:99
ns3::SystemThread::Equals
static bool Equals(ThreadId id)
Compares an ThreadId with the current ThreadId .
Definition: system-thread.cc:96
ns3::DefaultSimulatorImpl::GetContext
virtual uint32_t GetContext(void) const
Get the current simulation context.
Definition: default-simulator-impl.cc:410
NS_LOG_LOGIC
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
ns3::DefaultSimulatorImpl::EventsWithContext
std::list< struct EventWithContext > EventsWithContext
Container type for the events from a different context.
Definition: default-simulator-impl.h:101
ns3::SystemThread::Self
static ThreadId Self(void)
Returns the current thread Id.
Definition: system-thread.cc:89
ns3::Time::IsPositive
bool IsPositive(void) const
Exactly equivalent to t >= 0.
Definition: nstime.h:317
ns3::DefaultSimulatorImpl::m_uid
uint32_t m_uid
Next event unique id.
Definition: default-simulator-impl.h:122
ns3::DefaultSimulatorImpl::m_eventCount
uint64_t m_eventCount
The event count.
Definition: default-simulator-impl.h:130
log.h
Debug message logging.
ns3::DefaultSimulatorImpl::EventWithContext::timestamp
uint64_t timestamp
Event timestamp.
Definition: default-simulator-impl.h:96
default-simulator-impl.h
ns3::DefaultSimulatorImpl declaration.
ns3::DefaultSimulatorImpl::EventWithContext::context
uint32_t context
The event context.
Definition: default-simulator-impl.h:94
ns3::DefaultSimulatorImpl::m_currentContext
uint32_t m_currentContext
Execution context of the current event.
Definition: default-simulator-impl.h:128
ns3::SimulatorImpl
The SimulatorImpl base class.
Definition: simulator-impl.h:49
ns3::Scheduler
Maintain the event list.
Definition: scheduler.h:156
ns3::DefaultSimulatorImpl::DoDispose
virtual void DoDispose(void)
Destructor implementation.
Definition: default-simulator-impl.cc:85
simulator.h
ns3::Simulator declaration.
ns3::DefaultSimulatorImpl::IsFinished
virtual bool IsFinished(void) const
Check if the simulation should finish.
Definition: default-simulator-impl.cc:158
ns3::EventImpl
A simulation event.
Definition: event-impl.h:45
ns3::DefaultSimulatorImpl::EventWithContext
Wrap an event with its execution context.
Definition: default-simulator-impl.h:92
NS_LOG_FUNCTION
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Definition: log-macros-enabled.h:244
ns3::DefaultSimulatorImpl::SetScheduler
virtual void SetScheduler(ObjectFactory schedulerFactory)
Set the Scheduler to be used to manage the event list.
Definition: default-simulator-impl.cc:115
ns3::ObjectFactory::Create
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
Definition: object-factory.cc:98
ns3::DefaultSimulatorImpl::IsExpired
virtual bool IsExpired(const EventId &id) const
Check if an event has already run or been cancelled.
Definition: default-simulator-impl.cc:371
ns3::DefaultSimulatorImpl::~DefaultSimulatorImpl
~DefaultSimulatorImpl()
Destructor.
Definition: default-simulator-impl.cc:79
ptr.h
ns3::Ptr smart pointer declaration and implementation.
ns3::Simulator::NO_CONTEXT
@ NO_CONTEXT
Flag for events not associated with any particular context.
Definition: simulator.h:199
ns3::DefaultSimulatorImpl::EventWithContext::event
EventImpl * event
The event implementation.
Definition: default-simulator-impl.h:98
ns3::DefaultSimulatorImpl::m_currentUid
uint32_t m_currentUid
Unique id of the current event.
Definition: default-simulator-impl.h:124
ns3::DefaultSimulatorImpl::m_stop
bool m_stop
Flag calling for the end of the simulation.
Definition: default-simulator-impl.h:117
ns3::DefaultSimulatorImpl::Remove
virtual void Remove(const EventId &id)
Remove an event from the event list.
Definition: default-simulator-impl.cc:329
ns3::Object::DoDispose
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
ns3::DefaultSimulatorImpl::m_eventsWithContext
EventsWithContext m_eventsWithContext
The container of events from a different context.
Definition: default-simulator-impl.h:103
ns3::Scheduler::EventKey::m_uid
uint32_t m_uid
Event unique id.
Definition: scheduler.h:171