A Discrete-Event Network Simulator
API
realtime-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) 2008 University of Washington
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 
19 #include "simulator.h"
22 #include "scheduler.h"
23 #include "event-impl.h"
24 #include "synchronizer.h"
25 
26 #include "ptr.h"
27 #include "pointer.h"
28 #include "assert.h"
29 #include "fatal-error.h"
30 #include "log.h"
31 #include "system-mutex.h"
32 #include "boolean.h"
33 #include "enum.h"
34 
35 
36 #include <cmath>
37 
38 
45 namespace ns3 {
46 
47 // Note: Logging in this file is largely avoided due to the
48 // number of calls that are made to these functions and the possibility
49 // of causing recursions leading to stack overflow
50 NS_LOG_COMPONENT_DEFINE ("RealtimeSimulatorImpl");
51 
52 NS_OBJECT_ENSURE_REGISTERED (RealtimeSimulatorImpl);
53 
54 TypeId
56 {
57  static TypeId tid = TypeId ("ns3::RealtimeSimulatorImpl")
59  .SetGroupName ("Core")
60  .AddConstructor<RealtimeSimulatorImpl> ()
61  .AddAttribute ("SynchronizationMode",
62  "What to do if the simulation cannot keep up with real time.",
65  MakeEnumChecker (SYNC_BEST_EFFORT, "BestEffort",
66  SYNC_HARD_LIMIT, "HardLimit"))
67  .AddAttribute ("HardLimit",
68  "Maximum acceptable real-time jitter (used in conjunction with SynchronizationMode=HardLimit)",
69  TimeValue (Seconds (0.1)),
71  MakeTimeChecker ())
72  ;
73  return tid;
74 }
75 
76 
78 {
79  NS_LOG_FUNCTION (this);
80 
81  m_stop = false;
82  m_running = false;
83  // uids are allocated from 4.
84  // uid 0 is "invalid" events
85  // uid 1 is "now" events
86  // uid 2 is "destroy" events
87  m_uid = 4;
88  // before ::Run is entered, the m_currentUid will be zero
89  m_currentUid = 0;
90  m_currentTs = 0;
93  m_eventCount = 0;
94 
96 
97  // Be very careful not to do anything that would cause a change or assignment
98  // of the underlying reference counts of m_synchronizer or you will be sorry.
99  m_synchronizer = CreateObject<WallClockSynchronizer> ();
100 }
101 
103 {
104  NS_LOG_FUNCTION (this);
105 }
106 
107 void
109 {
110  NS_LOG_FUNCTION (this);
111  while (!m_events->IsEmpty ())
112  {
113  Scheduler::Event next = m_events->RemoveNext ();
114  next.impl->Unref ();
115  }
116  m_events = 0;
117  m_synchronizer = 0;
119 }
120 
121 void
123 {
124  NS_LOG_FUNCTION (this);
125 
126  //
127  // This function is only called with the private version "disconnected" from
128  // the main simulator functions. We rely on the user not calling
129  // Simulator::Destroy while there is a chance that a worker thread could be
130  // accessing the current instance of the private object. In practice this
131  // means shutting down the workers and doing a Join() before calling the
132  // Simulator::Destroy().
133  //
134  while (m_destroyEvents.empty () == false)
135  {
136  Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
137  m_destroyEvents.pop_front ();
138  NS_LOG_LOGIC ("handle destroy " << ev);
139  if (ev->IsCancelled () == false)
140  {
141  ev->Invoke ();
142  }
143  }
144 }
145 
146 void
148 {
149  NS_LOG_FUNCTION (this << schedulerFactory);
150 
151  Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
152 
153  {
155 
156  if (m_events != 0)
157  {
158  while (m_events->IsEmpty () == false)
159  {
160  Scheduler::Event next = m_events->RemoveNext ();
161  scheduler->Insert (next);
162  }
163  }
164  m_events = scheduler;
165  }
166 }
167 
168 void
170 {
171  //
172  // The idea here is to wait until the next event comes due. In the case of
173  // a realtime simulation, we want real time to be consumed between events.
174  // It is the realtime synchronizer that causes real time to be consumed by
175  // doing some kind of a wait.
176  //
177  // We need to be able to have external events (such as a packet reception event)
178  // cause us to re-evaluate our state. The way this works is that the synchronizer
179  // gets interrupted and returns. So, there is a possibility that things may change
180  // out from under us dynamically. In this case, we need to re-evaluate how long to
181  // wait in a for-loop until we have waited successfully (until a timeout) for the
182  // event at the head of the event list.
183  //
184  // m_synchronizer->Synchronize will return true if the wait was completed without
185  // interruption, otherwise it will return false indicating that something has changed
186  // out from under us. If we sit in the for-loop trying to synchronize until
187  // Synchronize() returns true, we will have successfully synchronized the execution
188  // time of the next event with the wall clock time of the synchronizer.
189  //
190 
191  for (;;)
192  {
193  uint64_t tsDelay = 0;
194  uint64_t tsNext = 0;
195 
196  //
197  // It is important to understand that m_currentTs is interpreted only as the
198  // timestamp of the last event we executed. Current time can a bit of a
199  // slippery concept in realtime mode. What we have here is a discrete event
200  // simulator, so the last event is, by definition, executed entirely at a single
201  // discrete time. This is the definition of m_currentTs. It really has
202  // nothing to do with the current real time, except that we are trying to arrange
203  // that at the instant of the beginning of event execution, the current real time
204  // and m_currentTs coincide.
205  //
206  // We use tsNow as the indication of the current real time.
207  //
208  uint64_t tsNow;
209 
210  {
212  //
213  // Since we are in realtime mode, the time to delay has got to be the
214  // difference between the current realtime and the timestamp of the next
215  // event. Since m_currentTs is actually the timestamp of the last event we
216  // executed, it's not particularly meaningful for us here since real time has
217  // certainly elapsed since it was last updated.
218  //
219  // It is possible that the current realtime has drifted past the next event
220  // time so we need to be careful about that and not delay in that case.
221  //
222  NS_ASSERT_MSG (m_synchronizer->Realtime (),
223  "RealtimeSimulatorImpl::ProcessOneEvent (): Synchronizer reports not Realtime ()");
224 
225  //
226  // tsNow is set to the normalized current real time. When the simulation was
227  // started, the current real time was effectively set to zero; so tsNow is
228  // the current "real" simulation time.
229  //
230  // tsNext is the simulation time of the next event we want to execute.
231  //
232  tsNow = m_synchronizer->GetCurrentRealtime ();
233  tsNext = NextTs ();
234 
235  //
236  // tsDelay is therefore the real time we need to delay in order to bring the
237  // real time in sync with the simulation time. If we wait for this amount of
238  // real time, we will accomplish moving the simulation time at the same rate
239  // as the real time. This is typically called "pacing" the simulation time.
240  //
241  // We do have to be careful if we are falling behind. If so, tsDelay must be
242  // zero. If we're late, don't dawdle.
243  //
244  if (tsNext <= tsNow)
245  {
246  tsDelay = 0;
247  }
248  else
249  {
250  tsDelay = tsNext - tsNow;
251  }
252 
253  //
254  // We've figured out how long we need to delay in order to pace the
255  // simulation time with the real time. We're going to sleep, but need
256  // to work with the synchronizer to make sure we're awakened if something
257  // external happens (like a packet is received). This next line resets
258  // the synchronizer so that any future event will cause it to interrupt.
259  //
260  m_synchronizer->SetCondition (false);
261  }
262 
263  //
264  // We have a time to delay. This time may actually not be valid anymore
265  // since we released the critical section immediately above, and a real-time
266  // ScheduleReal or ScheduleRealNow may have snuck in, well, between the
267  // closing brace above and this comment so to speak. If this is the case,
268  // that schedule operation will have done a synchronizer Signal() that
269  // will set the condition variable to true and cause the Synchronize call
270  // below to return immediately.
271  //
272  // It's easiest to understand if you just consider a short tsDelay that only
273  // requires a SpinWait down in the synchronizer. What will happen is that
274  // whan Synchronize calls SpinWait, SpinWait will look directly at its
275  // condition variable. Note that we set this condition variable to false
276  // inside the critical section above.
277  //
278  // SpinWait will go into a forever loop until either the time has expired or
279  // until the condition variable becomes true. A true condition indicates that
280  // the wait should stop. The condition is set to true by one of the Schedule
281  // methods of the simulator; so if we are in a wait down in Synchronize, and
282  // a Simulator::ScheduleReal is done, the wait down in Synchronize will exit and
283  // Synchronize will return false. This means we have not actually synchronized
284  // to the event expiration time. If no real-time schedule operation is done
285  // while down in Synchronize, the wait will time out and Synchronize will return
286  // true. This indicates that we have synchronized to the event time.
287  //
288  // So we need to stay in this for loop, looking for the next event timestamp and
289  // attempting to sleep until its due. If we've slept until the timestamp is due,
290  // Synchronize returns true and we break out of the sync loop. If an external
291  // event happens that requires a re-schedule, Synchronize returns false and
292  // we re-evaluate our timing by continuing in the loop.
293  //
294  // It is expected that tsDelay become shorter as external events interrupt our
295  // waits.
296  //
297  if (m_synchronizer->Synchronize (tsNow, tsDelay))
298  {
299  NS_LOG_LOGIC ("Interrupted ...");
300  break;
301  }
302 
303  //
304  // If we get to this point, we have been interrupted during a wait by a real-time
305  // schedule operation. This means all bets are off regarding tsDelay and we need
306  // to re-evaluate what it is we want to do. We'll loop back around in the
307  // for-loop and start again from scratch.
308  //
309  }
310 
311  //
312  // If we break out of the for-loop above, we have waited until the time specified
313  // by the event that was at the head of the event list when we started the process.
314  // Since there is a bunch of code that was executed outside a critical section (the
315  // Synchronize call) we cannot be sure that the event at the head of the event list
316  // is the one we think it is. What we can be sure of is that it is time to execute
317  // whatever event is at the head of this list if the list is in time order.
318  //
319  Scheduler::Event next;
320 
321  {
323 
324  //
325  // We do know we're waiting for an event, so there had better be an event on the
326  // event queue. Let's pull it off. When we release the critical section, the
327  // event we're working on won't be on the list and so subsequent operations won't
328  // mess with us.
329  //
330  NS_ASSERT_MSG (m_events->IsEmpty () == false,
331  "RealtimeSimulatorImpl::ProcessOneEvent(): event queue is empty");
332  next = m_events->RemoveNext ();
334  m_eventCount++;
335 
336  //
337  // We cannot make any assumption that "next" is the same event we originally waited
338  // for. We can only assume that only that it must be due and cannot cause time
339  // to move backward.
340  //
342  "RealtimeSimulatorImpl::ProcessOneEvent(): "
343  "next.GetTs() earlier than m_currentTs (list order error)");
344  NS_LOG_LOGIC ("handle " << next.key.m_ts);
345 
346  //
347  // Update the current simulation time to be the timestamp of the event we're
348  // executing. From the rest of the simulation's point of view, simulation time
349  // is frozen until the next event is executed.
350  //
351  m_currentTs = next.key.m_ts;
353  m_currentUid = next.key.m_uid;
354 
355  //
356  // We're about to run the event and we've done our best to synchronize this
357  // event execution time to real time. Now, if we're in SYNC_HARD_LIMIT mode
358  // we have to decide if we've done a good enough job and if we haven't, we've
359  // been asked to commit ritual suicide.
360  //
361  // We check the simulation time against the current real time to make this
362  // judgement.
363  //
365  {
366  uint64_t tsFinal = m_synchronizer->GetCurrentRealtime ();
367  uint64_t tsJitter;
368 
369  if (tsFinal >= m_currentTs)
370  {
371  tsJitter = tsFinal - m_currentTs;
372  }
373  else
374  {
375  tsJitter = m_currentTs - tsFinal;
376  }
377 
378  if (tsJitter > static_cast<uint64_t> (m_hardLimit.GetTimeStep ()))
379  {
380  NS_FATAL_ERROR ("RealtimeSimulatorImpl::ProcessOneEvent (): "
381  "Hard real-time limit exceeded (jitter = " << tsJitter << ")");
382  }
383  }
384  }
385 
386  //
387  // We have got the event we're about to execute completely disentangled from the
388  // event list so we can execute it outside a critical section without fear of someone
389  // changing things out from under us.
390 
391  EventImpl *event = next.impl;
392  m_synchronizer->EventStart ();
393  event->Invoke ();
394  m_synchronizer->EventEnd ();
395  event->Unref ();
396 }
397 
398 bool
400 {
401  bool rc;
402  {
404  rc = m_events->IsEmpty () || m_stop;
405  }
406 
407  return rc;
408 }
409 
410 //
411 // Peeks into event list. Should be called with critical section locked.
412 //
413 uint64_t
415 {
416  NS_ASSERT_MSG (m_events->IsEmpty () == false,
417  "RealtimeSimulatorImpl::NextTs(): event queue is empty");
418  Scheduler::Event ev = m_events->PeekNext ();
419  return ev.key.m_ts;
420 }
421 
422 void
424 {
425  NS_LOG_FUNCTION (this);
426 
427  NS_ASSERT_MSG (m_running == false,
428  "RealtimeSimulatorImpl::Run(): Simulator already running");
429 
430  // Set the current threadId as the main threadId
432 
433  m_stop = false;
434  m_running = true;
435  m_synchronizer->SetOrigin (m_currentTs);
436 
437  // Sleep until signalled
438  uint64_t tsNow = 0;
439  uint64_t tsDelay = 1000000000; // wait time of 1 second (in nanoseconds)
440 
441  while (!m_stop)
442  {
443  bool process = false;
444  {
446 
447  if (!m_events->IsEmpty ())
448  {
449  process = true;
450  }
451  else
452  {
453  // Get current timestamp while holding the critical section
454  tsNow = m_synchronizer->GetCurrentRealtime ();
455  }
456  }
457 
458  if (!process)
459  {
460  // Sleep until signalled
461  tsNow = m_synchronizer->Synchronize (tsNow, tsDelay);
462 
463  // Re-check event queue
464  continue;
465  }
466 
467  ProcessOneEvent ();
468  }
469 
470  //
471  // If the simulator stopped naturally by lack of events, make a
472  // consistency test to check that we didn't lose any events along the way.
473  //
474  {
476 
477  NS_ASSERT_MSG (m_events->IsEmpty () == false || m_unscheduledEvents == 0,
478  "RealtimeSimulatorImpl::Run(): Empty queue and unprocessed events");
479  }
480 
481  m_running = false;
482 }
483 
484 bool
486 {
487  return m_running;
488 }
489 
490 bool
492 {
493  return m_synchronizer->Realtime ();
494 }
495 
496 void
498 {
499  NS_LOG_FUNCTION (this);
500  m_stop = true;
501 }
502 
503 void
505 {
506  NS_LOG_FUNCTION (this << delay);
508 }
509 
510 //
511 // Schedule an event for a _relative_ time in the future.
512 //
513 EventId
515 {
516  NS_LOG_FUNCTION (this << delay << impl);
517 
518  Scheduler::Event ev;
519  {
521  //
522  // This is the reason we had to bring the absolute time calculation in from the
523  // simulator.h into the implementation. Since the implementations may be
524  // multi-threaded, we need this calculation to be atomic. You can see it is
525  // here since we are running in a CriticalSection.
526  //
527  Time tAbsolute = Simulator::Now () + delay;
528  NS_ASSERT_MSG (delay.IsPositive (), "RealtimeSimulatorImpl::Schedule(): Negative delay");
529  ev.impl = impl;
530  ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
531  ev.key.m_context = GetContext ();
532  ev.key.m_uid = m_uid;
533  m_uid++;
535  m_events->Insert (ev);
536  m_synchronizer->Signal ();
537  }
538 
539  return EventId (impl, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
540 }
541 
542 void
543 RealtimeSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &delay, EventImpl *impl)
544 {
545  NS_LOG_FUNCTION (this << context << delay << impl);
546 
547  {
549  uint64_t ts;
550 
552  {
553  ts = m_currentTs + delay.GetTimeStep ();
554  }
555  else
556  {
557  //
558  // If the simulator is running, we're pacing and have a meaningful
559  // realtime clock. If we're not, then m_currentTs is where we stopped.
560  //
561  ts = m_running ? m_synchronizer->GetCurrentRealtime () : m_currentTs;
562  ts += delay.GetTimeStep ();
563  }
564 
565  NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs");
566  Scheduler::Event ev;
567  ev.impl = impl;
568  ev.key.m_ts = ts;
569  ev.key.m_context = context;
570  ev.key.m_uid = m_uid;
571  m_uid++;
573  m_events->Insert (ev);
574  m_synchronizer->Signal ();
575  }
576 }
577 
578 EventId
580 {
581  NS_LOG_FUNCTION (this << impl);
582  Scheduler::Event ev;
583  {
585 
586  ev.impl = impl;
587  ev.key.m_ts = m_currentTs;
588  ev.key.m_context = GetContext ();
589  ev.key.m_uid = m_uid;
590  m_uid++;
592  m_events->Insert (ev);
593  m_synchronizer->Signal ();
594  }
595 
596  return EventId (impl, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
597 }
598 
599 Time
601 {
602  return TimeStep (m_currentTs);
603 }
604 
605 //
606 // Schedule an event for a _relative_ time in the future.
607 //
608 void
610 {
611  NS_LOG_FUNCTION (this << context << time << impl);
612 
613  {
615 
616  uint64_t ts = m_synchronizer->GetCurrentRealtime () + time.GetTimeStep ();
617  NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs");
618  Scheduler::Event ev;
619  ev.impl = impl;
620  ev.key.m_ts = ts;
621  ev.key.m_uid = m_uid;
622  m_uid++;
624  m_events->Insert (ev);
625  m_synchronizer->Signal ();
626  }
627 }
628 
629 void
631 {
632  NS_LOG_FUNCTION (this << time << impl);
633  ScheduleRealtimeWithContext (GetContext (), time, impl);
634 }
635 
636 void
638 {
639  NS_LOG_FUNCTION (this << context << impl);
640  {
642 
643  //
644  // If the simulator is running, we're pacing and have a meaningful
645  // realtime clock. If we're not, then m_currentTs is were we stopped.
646  //
647  uint64_t ts = m_running ? m_synchronizer->GetCurrentRealtime () : m_currentTs;
648  NS_ASSERT_MSG (ts >= m_currentTs,
649  "RealtimeSimulatorImpl::ScheduleRealtimeNowWithContext(): schedule for time < m_currentTs");
650  Scheduler::Event ev;
651  ev.impl = impl;
652  ev.key.m_ts = ts;
653  ev.key.m_uid = m_uid;
654  ev.key.m_context = context;
655  m_uid++;
657  m_events->Insert (ev);
658  m_synchronizer->Signal ();
659  }
660 }
661 
662 void
664 {
665  NS_LOG_FUNCTION (this << impl);
667 }
668 
669 Time
671 {
672  return TimeStep (m_synchronizer->GetCurrentRealtime ());
673 }
674 
675 EventId
677 {
678  NS_LOG_FUNCTION (this << impl);
679 
680  EventId id;
681  {
683 
684  //
685  // Time doesn't really matter here (especially in realtime mode). It is
686  // overridden by the uid of 2 which identifies this as an event to be
687  // executed at Simulator::Destroy time.
688  //
689  id = EventId (Ptr<EventImpl> (impl, false), m_currentTs, 0xffffffff, 2);
690  m_destroyEvents.push_back (id);
691  m_uid++;
692  }
693 
694  return id;
695 }
696 
697 Time
699 {
700  //
701  // If the event has expired, there is no delay until it runs. It is not the
702  // case that there is a negative time until it runs.
703  //
704  if (IsExpired (id))
705  {
706  return TimeStep (0);
707  }
708 
709  return TimeStep (id.GetTs () - m_currentTs);
710 }
711 
712 void
714 {
715  if (id.GetUid () == 2)
716  {
717  // destroy events.
718  for (DestroyEvents::iterator i = m_destroyEvents.begin ();
719  i != m_destroyEvents.end ();
720  i++)
721  {
722  if (*i == id)
723  {
724  m_destroyEvents.erase (i);
725  break;
726  }
727  }
728  return;
729  }
730  if (IsExpired (id))
731  {
732  return;
733  }
734 
735  {
737 
738  Scheduler::Event event;
739  event.impl = id.PeekEventImpl ();
740  event.key.m_ts = id.GetTs ();
741  event.key.m_context = id.GetContext ();
742  event.key.m_uid = id.GetUid ();
743 
744  m_events->Remove (event);
746  event.impl->Cancel ();
747  event.impl->Unref ();
748  }
749 }
750 
751 void
753 {
754  if (IsExpired (id) == false)
755  {
756  id.PeekEventImpl ()->Cancel ();
757  }
758 }
759 
760 bool
762 {
763  if (id.GetUid () == 2)
764  {
765  if (id.PeekEventImpl () == 0
766  || id.PeekEventImpl ()->IsCancelled ())
767  {
768  return true;
769  }
770  // destroy events.
771  for (DestroyEvents::const_iterator i = m_destroyEvents.begin ();
772  i != m_destroyEvents.end (); i++)
773  {
774  if (*i == id)
775  {
776  return false;
777  }
778  }
779  return true;
780  }
781 
782  //
783  // If the time of the event is less than the current timestamp of the
784  // simulator, the simulator has gone past the invocation time of the
785  // event, so the statement ev.GetTs () < m_currentTs does mean that
786  // the event has been fired even in realtime mode.
787  //
788  // The same is true for the next line involving the m_currentUid.
789  //
790  if (id.PeekEventImpl () == 0
791  || id.GetTs () < m_currentTs
792  || (id.GetTs () == m_currentTs && id.GetUid () <= m_currentUid)
793  || id.PeekEventImpl ()->IsCancelled ())
794  {
795  return true;
796  }
797  else
798  {
799  return false;
800  }
801 }
802 
803 Time
805 {
806  return TimeStep (0x7fffffffffffffffLL);
807 }
808 
809 // System ID for non-distributed simulation is always zero
810 uint32_t
812 {
813  return 0;
814 }
815 
816 uint32_t
818 {
819  return m_currentContext;
820 }
821 
822 uint64_t
824 {
825  return m_eventCount;
826 }
827 
828 void
830 {
831  NS_LOG_FUNCTION (this << mode);
832  m_synchronizationMode = mode;
833 }
834 
837 {
838  NS_LOG_FUNCTION (this);
839  return m_synchronizationMode;
840 }
841 
842 void
844 {
845  NS_LOG_FUNCTION (this << limit);
846  m_hardLimit = limit;
847 }
848 
849 Time
851 {
852  NS_LOG_FUNCTION (this);
853  return m_hardLimit;
854 }
855 
856 } // namespace ns3
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
ns3::RealtimeSimulatorImpl::m_events
Ptr< Scheduler > m_events
The event list.
Definition: realtime-simulator-impl.h:196
ns3::RealtimeSimulatorImpl::GetEventCount
virtual uint64_t GetEventCount(void) const
Get the number of events executed.
Definition: realtime-simulator-impl.cc:823
ns3::RealtimeSimulatorImpl::SetSynchronizationMode
void SetSynchronizationMode(RealtimeSimulatorImpl::SynchronizationMode mode)
Set the SynchronizationMode.
Definition: realtime-simulator-impl.cc:829
NS_OBJECT_ENSURE_REGISTERED
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
fatal-error.h
NS_FATAL_x macro definitions.
ns3::MakeTimeChecker
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
ns3::RealtimeSimulatorImpl::Schedule
virtual EventId Schedule(const Time &delay, EventImpl *event)
Schedule a future event execution (in the same context).
Definition: realtime-simulator-impl.cc:514
ns3::RealtimeSimulatorImpl::Run
virtual void Run(void)
Run the simulation.
Definition: realtime-simulator-impl.cc:423
ns3::RealtimeSimulatorImpl::RealtimeNow
Time RealtimeNow(void) const
Get the current real time from the synchronizer.
Definition: realtime-simulator-impl.cc:670
ns3::EventId
An identifier for simulation events.
Definition: event-id.h:54
ns3::RealtimeSimulatorImpl::SYNC_BEST_EFFORT
@ SYNC_BEST_EFFORT
Make a best effort to keep synced to real-time.
Definition: realtime-simulator-impl.h:75
ns3::RealtimeSimulatorImpl::Remove
virtual void Remove(const EventId &ev)
Remove an event from the event list.
Definition: realtime-simulator-impl.cc:713
ns3::Simulator::Now
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
ns3
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns3::RealtimeSimulatorImpl::m_uid
uint32_t m_uid
Unique id of the current event.
Definition: realtime-simulator-impl.h:200
ns3::RealtimeSimulatorImpl
Realtime version of SimulatorImpl.
Definition: realtime-simulator-impl.h:57
boolean.h
ns3::BooleanValue attribute value declarations.
ns3::RealtimeSimulatorImpl::SetScheduler
virtual void SetScheduler(ObjectFactory schedulerFactory)
Set the Scheduler to be used to manage the event list.
Definition: realtime-simulator-impl.cc:147
ns3::RealtimeSimulatorImpl::Now
virtual Time Now(void) const
Return the current simulation virtual time.
Definition: realtime-simulator-impl.cc:600
ns3::Scheduler::Event::impl
EventImpl * impl
Pointer to the event implementation.
Definition: scheduler.h:183
ns3::RealtimeSimulatorImpl::m_currentContext
uint32_t m_currentContext
The event list.
Definition: realtime-simulator-impl.h:206
ns3::MakeEnumChecker
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:161
ns3::RealtimeSimulatorImpl::Cancel
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...
Definition: realtime-simulator-impl.cc:752
ns3::RealtimeSimulatorImpl::Stop
virtual void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: realtime-simulator-impl.cc:497
synchronizer.h
ns3::Synchronizer declaration.
ns3::RealtimeSimulatorImpl::ScheduleRealtimeNow
void ScheduleRealtimeNow(EventImpl *event)
Schedule an event to run at the current virtual time.
Definition: realtime-simulator-impl.cc:663
ns3::RealtimeSimulatorImpl::GetMaximumSimulationTime
virtual Time GetMaximumSimulationTime(void) const
Get the maximum representable simulation time.
Definition: realtime-simulator-impl.cc:804
assert.h
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
ns3::RealtimeSimulatorImpl::ScheduleRealtimeNowWithContext
void ScheduleRealtimeNowWithContext(uint32_t context, EventImpl *event)
Schedule an event to run at the current virtual time.
Definition: realtime-simulator-impl.cc:637
ns3::RealtimeSimulatorImpl::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: realtime-simulator-impl.cc:676
ns3::RealtimeSimulatorImpl::m_synchronizer
Ptr< Synchronizer > m_synchronizer
The synchronizer in use to track real time.
Definition: realtime-simulator-impl.h:215
ns3::RealtimeSimulatorImpl::ScheduleNow
virtual EventId ScheduleNow(EventImpl *event)
Schedule an event to run at the current virtual time.
Definition: realtime-simulator-impl.cc:579
ns3::RealtimeSimulatorImpl::SynchronizationMode
SynchronizationMode
What to do when we can't maintain real time synchrony.
Definition: realtime-simulator-impl.h:69
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::RealtimeSimulatorImpl::NextTs
uint64_t NextTs(void) const
Get the timestep of the next event.
Definition: realtime-simulator-impl.cc:414
ns3::TypeId::SetParent
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
ns3::EnumValue
Hold variables of type enum.
Definition: enum.h:55
scheduler.h
ns3::Scheduler abstract base class, ns3::Scheduler::Event and ns3::Scheduler::EventKey declarations.
ns3::RealtimeSimulatorImpl::ScheduleWithContext
virtual void ScheduleWithContext(uint32_t context, const Time &delay, EventImpl *event)
Schedule a future event execution (in a different context).
Definition: realtime-simulator-impl.cc:543
ns3::RealtimeSimulatorImpl::RealtimeSimulatorImpl
RealtimeSimulatorImpl()
Constructor.
Definition: realtime-simulator-impl.cc:77
ns3::Scheduler::EventKey::m_ts
uint64_t m_ts
Event time stamp.
Definition: scheduler.h:170
ns3::RealtimeSimulatorImpl::SetHardLimit
void SetHardLimit(Time limit)
Set the fatal error threshold for SynchronizationMode SYNC_HARD_LIMIT.
Definition: realtime-simulator-impl.cc:843
ns3::RealtimeSimulatorImpl::IsFinished
virtual bool IsFinished(void) const
Check if the simulation should finish.
Definition: realtime-simulator-impl.cc:399
ns3::RealtimeSimulatorImpl::m_hardLimit
Time m_hardLimit
The maximum allowable drift from real-time in SYNC_HARD_LIMIT mode.
Definition: realtime-simulator-impl.h:221
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
NS_FATAL_ERROR
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
ns3::RealtimeSimulatorImpl::~RealtimeSimulatorImpl
~RealtimeSimulatorImpl()
Destructor.
Definition: realtime-simulator-impl.cc:102
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::RealtimeSimulatorImpl::ScheduleRealtimeWithContext
void ScheduleRealtimeWithContext(uint32_t context, const Time &delay, EventImpl *event)
Schedule a future event execution (in a different context).
Definition: realtime-simulator-impl.cc:609
ns3::Scheduler::EventKey::m_context
uint32_t m_context
Event context.
Definition: scheduler.h:172
ns3::RealtimeSimulatorImpl::GetContext
virtual uint32_t GetContext(void) const
Get the current simulation context.
Definition: realtime-simulator-impl.cc:817
wall-clock-synchronizer.h
ns3::WallClockSynchronizer declaration.
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
event-impl.h
ns3::EventImpl declarations.
ns3::RealtimeSimulatorImpl::m_running
bool m_running
Is the simulator currently running.
Definition: realtime-simulator-impl.h:187
ns3::Time
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
ns3::RealtimeSimulatorImpl::ProcessOneEvent
void ProcessOneEvent(void)
Process the next event.
Definition: realtime-simulator-impl.cc:169
ns3::SimpleRefCount::Unref
void Unref(void) const
Decrement the reference count.
Definition: simple-ref-count.h:116
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::RealtimeSimulatorImpl::m_currentTs
uint64_t m_currentTs
Execution context.
Definition: realtime-simulator-impl.h:204
ns3::RealtimeSimulatorImpl::GetDelayLeft
virtual Time GetDelayLeft(const EventId &id) const
Get the remaining time until this event will execute.
Definition: realtime-simulator-impl.cc:698
ns3::RealtimeSimulatorImpl::m_unscheduledEvents
int m_unscheduledEvents
Unique id for the next event to be scheduled.
Definition: realtime-simulator-impl.h:198
ns3::SystemThread::Equals
static bool Equals(ThreadId id)
Compares an ThreadId with the current ThreadId .
Definition: system-thread.cc:96
NS_LOG_LOGIC
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
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::RealtimeSimulatorImpl::GetSystemId
virtual uint32_t GetSystemId(void) const
Get the system id of this simulator.
Definition: realtime-simulator-impl.cc:811
log.h
Debug message logging.
system-mutex.h
System-independent mutex primitive, ns3::SystemMutex, and ns3::CriticalSection.
ns3::SimulatorImpl
The SimulatorImpl base class.
Definition: simulator-impl.h:49
ns3::RealtimeSimulatorImpl::ScheduleRealtime
void ScheduleRealtime(const Time &delay, EventImpl *event)
Schedule a future event execution (in the same context).
Definition: realtime-simulator-impl.cc:630
ns3::RealtimeSimulatorImpl::DoDispose
virtual void DoDispose(void)
Destructor implementation.
Definition: realtime-simulator-impl.cc:108
ns3::Scheduler
Maintain the event list.
Definition: scheduler.h:156
ns3::Seconds
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
ns3::RealtimeSimulatorImpl::m_eventCount
uint64_t m_eventCount
The event count.
Definition: realtime-simulator-impl.h:208
ns3::RealtimeSimulatorImpl::m_mutex
SystemMutex m_mutex
Mutex to control access to key state.
Definition: realtime-simulator-impl.h:212
simulator.h
ns3::Simulator declaration.
ns3::MakeEnumAccessor
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: enum.h:203
ns3::EventImpl
A simulation event.
Definition: event-impl.h:45
ns3::TimeValue
AttributeValue implementation for Time.
Definition: nstime.h:1353
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
realtime-simulator-impl.h
ns3::RealtimeSimulatorImpl declaration.
ns3::RealtimeSimulatorImpl::GetHardLimit
Time GetHardLimit(void) const
Get the current fatal error threshold for SynchronizationMode SYNC_HARD_LIMIT.
Definition: realtime-simulator-impl.cc:850
ns3::RealtimeSimulatorImpl::m_main
SystemThread::ThreadId m_main
Main SystemThread.
Definition: realtime-simulator-impl.h:224
ns3::RealtimeSimulatorImpl::m_destroyEvents
DestroyEvents m_destroyEvents
Container for events to be run at destroy time.
Definition: realtime-simulator-impl.h:183
ns3::RealtimeSimulatorImpl::Realtime
bool Realtime(void) const
Check that the Synchronizer is locked to the real time clock.
Definition: realtime-simulator-impl.cc:491
ns3::RealtimeSimulatorImpl::Destroy
virtual void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: realtime-simulator-impl.cc:122
ns3::RealtimeSimulatorImpl::m_stop
bool m_stop
Has the stopping condition been reached?
Definition: realtime-simulator-impl.h:185
ns3::ObjectFactory::Create
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
Definition: object-factory.cc:98
ns3::RealtimeSimulatorImpl::Running
bool Running(void) const
Is the simulator running?
Definition: realtime-simulator-impl.cc:485
ns3::RealtimeSimulatorImpl::m_synchronizationMode
SynchronizationMode m_synchronizationMode
SynchronizationMode policy.
Definition: realtime-simulator-impl.h:218
ns3::RealtimeSimulatorImpl::GetTypeId
static TypeId GetTypeId(void)
Get the registered TypeId for this class.
Definition: realtime-simulator-impl.cc:55
ns3::RealtimeSimulatorImpl::GetSynchronizationMode
RealtimeSimulatorImpl::SynchronizationMode GetSynchronizationMode(void) const
Get the SynchronizationMode.
Definition: realtime-simulator-impl.cc:836
ns3::RealtimeSimulatorImpl::m_currentUid
uint32_t m_currentUid
Timestep of the current event.
Definition: realtime-simulator-impl.h:202
ns3::RealtimeSimulatorImpl::IsExpired
virtual bool IsExpired(const EventId &ev) const
Check if an event has already run or been cancelled.
Definition: realtime-simulator-impl.cc:761
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::RealtimeSimulatorImpl::SYNC_HARD_LIMIT
@ SYNC_HARD_LIMIT
Keep to real time within the hard limit tolerance configured with SetHardLimit, or die trying.
Definition: realtime-simulator-impl.h:84
ns3::Object::DoDispose
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
ns3::MakeTimeAccessor
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1354
ns3::Scheduler::EventKey::m_uid
uint32_t m_uid
Event unique id.
Definition: scheduler.h:171
enum.h
ns3::EnumValue attribute value declarations.