A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 // Note: Logging in this file is largely avoided due to the
39 // number of calls that are made to these functions and the possibility
40 // of causing recursions leading to stack overflow
41 
42 NS_LOG_COMPONENT_DEFINE ("RealtimeSimulatorImpl");
43 
44 namespace ns3 {
45 
46 NS_OBJECT_ENSURE_REGISTERED (RealtimeSimulatorImpl);
47 
48 TypeId
50 {
51  static TypeId tid = TypeId ("ns3::RealtimeSimulatorImpl")
53  .AddConstructor<RealtimeSimulatorImpl> ()
54  .AddAttribute ("SynchronizationMode",
55  "What to do if the simulation cannot keep up with real time.",
58  MakeEnumChecker (SYNC_BEST_EFFORT, "BestEffort",
59  SYNC_HARD_LIMIT, "HardLimit"))
60  .AddAttribute ("HardLimit",
61  "Maximum acceptable real-time jitter (used in conjunction with SynchronizationMode=HardLimit)",
62  TimeValue (Seconds (0.1)),
63  MakeTimeAccessor (&RealtimeSimulatorImpl::m_hardLimit),
64  MakeTimeChecker ())
65  ;
66  return tid;
67 }
68 
69 
71 {
72  NS_LOG_FUNCTION (this);
73 
74  m_stop = false;
75  m_running = false;
76  // uids are allocated from 4.
77  // uid 0 is "invalid" events
78  // uid 1 is "now" events
79  // uid 2 is "destroy" events
80  m_uid = 4;
81  // before ::Run is entered, the m_currentUid will be zero
82  m_currentUid = 0;
83  m_currentTs = 0;
84  m_currentContext = 0xffffffff;
86 
88 
89  // Be very careful not to do anything that would cause a change or assignment
90  // of the underlying reference counts of m_synchronizer or you will be sorry.
91  m_synchronizer = CreateObject<WallClockSynchronizer> ();
92 }
93 
95 {
96  NS_LOG_FUNCTION (this);
97 }
98 
99 void
101 {
102  NS_LOG_FUNCTION (this);
103  while (!m_events->IsEmpty ())
104  {
105  Scheduler::Event next = m_events->RemoveNext ();
106  next.impl->Unref ();
107  }
108  m_events = 0;
109  m_synchronizer = 0;
111 }
112 
113 void
115 {
116  NS_LOG_FUNCTION (this);
117 
118  //
119  // This function is only called with the private version "disconnected" from
120  // the main simulator functions. We rely on the user not calling
121  // Simulator::Destroy while there is a chance that a worker thread could be
122  // accessing the current instance of the private object. In practice this
123  // means shutting down the workers and doing a Join() before calling the
124  // Simulator::Destroy().
125  //
126  while (m_destroyEvents.empty () == false)
127  {
128  Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
129  m_destroyEvents.pop_front ();
130  NS_LOG_LOGIC ("handle destroy " << ev);
131  if (ev->IsCancelled () == false)
132  {
133  ev->Invoke ();
134  }
135  }
136 }
137 
138 void
140 {
141  NS_LOG_FUNCTION (this << schedulerFactory);
142 
143  Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
144 
145  {
147 
148  if (m_events != 0)
149  {
150  while (m_events->IsEmpty () == false)
151  {
152  Scheduler::Event next = m_events->RemoveNext ();
153  scheduler->Insert (next);
154  }
155  }
156  m_events = scheduler;
157  }
158 }
159 
160 void
162 {
163  //
164  // The idea here is to wait until the next event comes due. In the case of
165  // a realtime simulation, we want real time to be consumed between events.
166  // It is the realtime synchronizer that causes real time to be consumed by
167  // doing some kind of a wait.
168  //
169  // We need to be able to have external events (such as a packet reception event)
170  // cause us to re-evaluate our state. The way this works is that the synchronizer
171  // gets interrupted and returns. So, there is a possibility that things may change
172  // out from under us dynamically. In this case, we need to re-evaluate how long to
173  // wait in a for-loop until we have waited sucessfully (until a timeout) for the
174  // event at the head of the event list.
175  //
176  // m_synchronizer->Synchronize will return true if the wait was completed without
177  // interruption, otherwise it will return false indicating that something has changed
178  // out from under us. If we sit in the for-loop trying to synchronize until
179  // Synchronize() returns true, we will have successfully synchronized the execution
180  // time of the next event with the wall clock time of the synchronizer.
181  //
182 
183  for (;;)
184  {
185  uint64_t tsDelay = 0;
186  uint64_t tsNext = 0;
187 
188  //
189  // It is important to understand that m_currentTs is interpreted only as the
190  // timestamp of the last event we executed. Current time can a bit of a
191  // slippery concept in realtime mode. What we have here is a discrete event
192  // simulator, so the last event is, by defintion, executed entirely at a single
193  // discrete time. This is the definition of m_currentTs. It really has
194  // nothing to do with the current real time, except that we are trying to arrange
195  // that at the instant of the beginning of event execution, the current real time
196  // and m_currentTs coincide.
197  //
198  // We use tsNow as the indication of the current real time.
199  //
200  uint64_t tsNow;
201 
202  {
204  //
205  // Since we are in realtime mode, the time to delay has got to be the
206  // difference between the current realtime and the timestamp of the next
207  // event. Since m_currentTs is actually the timestamp of the last event we
208  // executed, it's not particularly meaningful for us here since real time has
209  // certainly elapsed since it was last updated.
210  //
211  // It is possible that the current realtime has drifted past the next event
212  // time so we need to be careful about that and not delay in that case.
213  //
214  NS_ASSERT_MSG (m_synchronizer->Realtime (),
215  "RealtimeSimulatorImpl::ProcessOneEvent (): Synchronizer reports not Realtime ()");
216 
217  //
218  // tsNow is set to the normalized current real time. When the simulation was
219  // started, the current real time was effectively set to zero; so tsNow is
220  // the current "real" simulation time.
221  //
222  // tsNext is the simulation time of the next event we want to execute.
223  //
224  tsNow = m_synchronizer->GetCurrentRealtime ();
225  tsNext = NextTs ();
226 
227  //
228  // tsDelay is therefore the real time we need to delay in order to bring the
229  // real time in sync with the simulation time. If we wait for this amount of
230  // real time, we will accomplish moving the simulation time at the same rate
231  // as the real time. This is typically called "pacing" the simulation time.
232  //
233  // We do have to be careful if we are falling behind. If so, tsDelay must be
234  // zero. If we're late, don't dawdle.
235  //
236  if (tsNext <= tsNow)
237  {
238  tsDelay = 0;
239  }
240  else
241  {
242  tsDelay = tsNext - tsNow;
243  }
244 
245  //
246  // We've figured out how long we need to delay in order to pace the
247  // simulation time with the real time. We're going to sleep, but need
248  // to work with the synchronizer to make sure we're awakened if something
249  // external happens (like a packet is received). This next line resets
250  // the synchronizer so that any future event will cause it to interrupt.
251  //
252  m_synchronizer->SetCondition (false);
253  }
254 
255  //
256  // We have a time to delay. This time may actually not be valid anymore
257  // since we released the critical section immediately above, and a real-time
258  // ScheduleReal or ScheduleRealNow may have snuck in, well, between the
259  // closing brace above and this comment so to speak. If this is the case,
260  // that schedule operation will have done a synchronizer Signal() that
261  // will set the condition variable to true and cause the Synchronize call
262  // below to return immediately.
263  //
264  // It's easiest to understand if you just consider a short tsDelay that only
265  // requires a SpinWait down in the synchronizer. What will happen is that
266  // whan Synchronize calls SpinWait, SpinWait will look directly at its
267  // condition variable. Note that we set this condition variable to false
268  // inside the critical section above.
269  //
270  // SpinWait will go into a forever loop until either the time has expired or
271  // until the condition variable becomes true. A true condition indicates that
272  // the wait should stop. The condition is set to true by one of the Schedule
273  // methods of the simulator; so if we are in a wait down in Synchronize, and
274  // a Simulator::ScheduleReal is done, the wait down in Synchronize will exit and
275  // Synchronize will return false. This means we have not actually synchronized
276  // to the event expiration time. If no real-time schedule operation is done
277  // while down in Synchronize, the wait will time out and Synchronize will return
278  // true. This indicates that we have synchronized to the event time.
279  //
280  // So we need to stay in this for loop, looking for the next event timestamp and
281  // attempting to sleep until its due. If we've slept until the timestamp is due,
282  // Synchronize returns true and we break out of the sync loop. If an external
283  // event happens that requires a re-schedule, Synchronize returns false and
284  // we re-evaluate our timing by continuing in the loop.
285  //
286  // It is expected that tsDelay become shorter as external events interrupt our
287  // waits.
288  //
289  if (m_synchronizer->Synchronize (tsNow, tsDelay))
290  {
291  NS_LOG_LOGIC ("Interrupted ...");
292  break;
293  }
294 
295  //
296  // If we get to this point, we have been interrupted during a wait by a real-time
297  // schedule operation. This means all bets are off regarding tsDelay and we need
298  // to re-evaluate what it is we want to do. We'll loop back around in the
299  // for-loop and start again from scratch.
300  //
301  }
302 
303  //
304  // If we break out of the for-loop above, we have waited until the time specified
305  // by the event that was at the head of the event list when we started the process.
306  // Since there is a bunch of code that was executed outside a critical section (the
307  // Synchronize call) we cannot be sure that the event at the head of the event list
308  // is the one we think it is. What we can be sure of is that it is time to execute
309  // whatever event is at the head of this list if the list is in time order.
310  //
311  Scheduler::Event next;
312 
313  {
315 
316  //
317  // We do know we're waiting for an event, so there had better be an event on the
318  // event queue. Let's pull it off. When we release the critical section, the
319  // event we're working on won't be on the list and so subsequent operations won't
320  // mess with us.
321  //
322  NS_ASSERT_MSG (m_events->IsEmpty () == false,
323  "RealtimeSimulatorImpl::ProcessOneEvent(): event queue is empty");
324  next = m_events->RemoveNext ();
326 
327  //
328  // We cannot make any assumption that "next" is the same event we originally waited
329  // for. We can only assume that only that it must be due and cannot cause time
330  // to move backward.
331  //
332  NS_ASSERT_MSG (next.key.m_ts >= m_currentTs,
333  "RealtimeSimulatorImpl::ProcessOneEvent(): "
334  "next.GetTs() earlier than m_currentTs (list order error)");
335  NS_LOG_LOGIC ("handle " << next.key.m_ts);
336 
337  //
338  // Update the current simulation time to be the timestamp of the event we're
339  // executing. From the rest of the simulation's point of view, simulation time
340  // is frozen until the next event is executed.
341  //
342  m_currentTs = next.key.m_ts;
343  m_currentContext = next.key.m_context;
344  m_currentUid = next.key.m_uid;
345 
346  //
347  // We're about to run the event and we've done our best to synchronize this
348  // event execution time to real time. Now, if we're in SYNC_HARD_LIMIT mode
349  // we have to decide if we've done a good enough job and if we haven't, we've
350  // been asked to commit ritual suicide.
351  //
352  // We check the simulation time against the current real time to make this
353  // judgement.
354  //
356  {
357  uint64_t tsFinal = m_synchronizer->GetCurrentRealtime ();
358  uint64_t tsJitter;
359 
360  if (tsFinal >= m_currentTs)
361  {
362  tsJitter = tsFinal - m_currentTs;
363  }
364  else
365  {
366  tsJitter = m_currentTs - tsFinal;
367  }
368 
369  if (tsJitter > static_cast<uint64_t>(m_hardLimit.GetTimeStep ()))
370  {
371  NS_FATAL_ERROR ("RealtimeSimulatorImpl::ProcessOneEvent (): "
372  "Hard real-time limit exceeded (jitter = " << tsJitter << ")");
373  }
374  }
375  }
376 
377  //
378  // We have got the event we're about to execute completely disentangled from the
379  // event list so we can execute it outside a critical section without fear of someone
380  // changing things out from under us.
381 
382  EventImpl *event = next.impl;
383  m_synchronizer->EventStart ();
384  event->Invoke ();
385  m_synchronizer->EventEnd ();
386  event->Unref ();
387 }
388 
389 bool
391 {
392  bool rc;
393  {
395  rc = m_events->IsEmpty () || m_stop;
396  }
397 
398  return rc;
399 }
400 
401 //
402 // Peeks into event list. Should be called with critical section locked.
403 //
404 uint64_t
406 {
407  NS_ASSERT_MSG (m_events->IsEmpty () == false,
408  "RealtimeSimulatorImpl::NextTs(): event queue is empty");
409  Scheduler::Event ev = m_events->PeekNext ();
410  return ev.key.m_ts;
411 }
412 
413 void
415 {
416  NS_LOG_FUNCTION (this);
417 
418  NS_ASSERT_MSG (m_running == false,
419  "RealtimeSimulatorImpl::Run(): Simulator already running");
420 
421  // Set the current threadId as the main threadId
423 
424  m_stop = false;
425  m_running = true;
426  m_synchronizer->SetOrigin (m_currentTs);
427 
428  // Sleep until signalled
429  uint64_t tsNow;
430  uint64_t tsDelay = 1000000000; // wait time of 1 second (in nanoseconds)
431 
432  while (!m_stop)
433  {
434  bool process = false;
435  {
437 
438  if (!m_events->IsEmpty ())
439  {
440  process = true;
441  }
442  else
443  {
444  // Get current timestamp while holding the critical section
445  tsNow = m_synchronizer->GetCurrentRealtime ();
446  }
447  }
448 
449  if (!process)
450  {
451  // Sleep until signalled
452  tsNow = m_synchronizer->Synchronize (tsNow, tsDelay);
453 
454  // Re-check event queue
455  continue;
456  }
457 
458  ProcessOneEvent ();
459  }
460 
461  //
462  // If the simulator stopped naturally by lack of events, make a
463  // consistency test to check that we didn't lose any events along the way.
464  //
465  {
467 
468  NS_ASSERT_MSG (m_events->IsEmpty () == false || m_unscheduledEvents == 0,
469  "RealtimeSimulatorImpl::Run(): Empty queue and unprocessed events");
470  }
471 
472  m_running = false;
473 }
474 
475 bool
477 {
478  return m_running;
479 }
480 
481 bool
483 {
484  return m_synchronizer->Realtime ();
485 }
486 
487 void
489 {
490  NS_LOG_FUNCTION (this);
491  m_stop = true;
492 }
493 
494 void
496 {
497  NS_LOG_FUNCTION (this << time);
499 }
500 
501 //
502 // Schedule an event for a _relative_ time in the future.
503 //
504 EventId
506 {
507  NS_LOG_FUNCTION (this << time << impl);
508 
509  Scheduler::Event ev;
510  {
512  //
513  // This is the reason we had to bring the absolute time calcualtion in from the
514  // simulator.h into the implementation. Since the implementations may be
515  // multi-threaded, we need this calculation to be atomic. You can see it is
516  // here since we are running in a CriticalSection.
517  //
518  Time tAbsolute = Simulator::Now () + time;
519  NS_ASSERT_MSG (tAbsolute.IsPositive (), "RealtimeSimulatorImpl::Schedule(): Negative time");
520  NS_ASSERT_MSG (tAbsolute >= TimeStep (m_currentTs), "RealtimeSimulatorImpl::Schedule(): time < m_currentTs");
521  ev.impl = impl;
522  ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
523  ev.key.m_context = GetContext ();
524  ev.key.m_uid = m_uid;
525  m_uid++;
527  m_events->Insert (ev);
528  m_synchronizer->Signal ();
529  }
530 
531  return EventId (impl, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
532 }
533 
534 void
535 RealtimeSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &time, EventImpl *impl)
536 {
537  NS_LOG_FUNCTION (this << context << time << impl);
538 
539  {
541  uint64_t ts;
542 
544  {
545  ts = m_currentTs + time.GetTimeStep ();
546  }
547  else
548  {
549  //
550  // If the simulator is running, we're pacing and have a meaningful
551  // realtime clock. If we're not, then m_currentTs is where we stopped.
552  //
553  ts = m_running ? m_synchronizer->GetCurrentRealtime () : m_currentTs;
554  ts += time.GetTimeStep ();
555  }
556 
557  NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs");
558  Scheduler::Event ev;
559  ev.impl = impl;
560  ev.key.m_ts = ts;
561  ev.key.m_context = context;
562  ev.key.m_uid = m_uid;
563  m_uid++;
565  m_events->Insert (ev);
566  m_synchronizer->Signal ();
567  }
568 }
569 
570 EventId
572 {
573  NS_LOG_FUNCTION (this << impl);
574  Scheduler::Event ev;
575  {
577 
578  ev.impl = impl;
579  ev.key.m_ts = m_currentTs;
580  ev.key.m_context = GetContext ();
581  ev.key.m_uid = m_uid;
582  m_uid++;
584  m_events->Insert (ev);
585  m_synchronizer->Signal ();
586  }
587 
588  return EventId (impl, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
589 }
590 
591 Time
593 {
594  return TimeStep (m_currentTs);
595 }
596 
597 //
598 // Schedule an event for a _relative_ time in the future.
599 //
600 void
602 {
603  NS_LOG_FUNCTION (this << context << time << impl);
604 
605  {
607 
608  uint64_t ts = m_synchronizer->GetCurrentRealtime () + time.GetTimeStep ();
609  NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs");
610  Scheduler::Event ev;
611  ev.impl = impl;
612  ev.key.m_ts = ts;
613  ev.key.m_uid = m_uid;
614  m_uid++;
616  m_events->Insert (ev);
617  m_synchronizer->Signal ();
618  }
619 }
620 
621 void
623 {
624  NS_LOG_FUNCTION (this << time << impl);
625  ScheduleRealtimeWithContext (GetContext (), time, impl);
626 }
627 
628 void
630 {
631  NS_LOG_FUNCTION (this << context << impl);
632  {
634 
635  //
636  // If the simulator is running, we're pacing and have a meaningful
637  // realtime clock. If we're not, then m_currentTs is were we stopped.
638  //
639  uint64_t ts = m_running ? m_synchronizer->GetCurrentRealtime () : m_currentTs;
640  NS_ASSERT_MSG (ts >= m_currentTs,
641  "RealtimeSimulatorImpl::ScheduleRealtimeNowWithContext(): schedule for time < m_currentTs");
642  Scheduler::Event ev;
643  ev.impl = impl;
644  ev.key.m_ts = ts;
645  ev.key.m_uid = m_uid;
646  ev.key.m_context = context;
647  m_uid++;
649  m_events->Insert (ev);
650  m_synchronizer->Signal ();
651  }
652 }
653 
654 void
656 {
657  NS_LOG_FUNCTION (this << impl);
659 }
660 
661 Time
663 {
664  return TimeStep (m_synchronizer->GetCurrentRealtime ());
665 }
666 
667 EventId
669 {
670  NS_LOG_FUNCTION (this << impl);
671 
672  EventId id;
673  {
675 
676  //
677  // Time doesn't really matter here (especially in realtime mode). It is
678  // overridden by the uid of 2 which identifies this as an event to be
679  // executed at Simulator::Destroy time.
680  //
681  id = EventId (Ptr<EventImpl> (impl, false), m_currentTs, 0xffffffff, 2);
682  m_destroyEvents.push_back (id);
683  m_uid++;
684  }
685 
686  return id;
687 }
688 
689 Time
691 {
692  //
693  // If the event has expired, there is no delay until it runs. It is not the
694  // case that there is a negative time until it runs.
695  //
696  if (IsExpired (id))
697  {
698  return TimeStep (0);
699  }
700 
701  return TimeStep (id.GetTs () - m_currentTs);
702 }
703 
704 void
706 {
707  if (id.GetUid () == 2)
708  {
709  // destroy events.
710  for (DestroyEvents::iterator i = m_destroyEvents.begin ();
711  i != m_destroyEvents.end ();
712  i++)
713  {
714  if (*i == id)
715  {
716  m_destroyEvents.erase (i);
717  break;
718  }
719  }
720  return;
721  }
722  if (IsExpired (id))
723  {
724  return;
725  }
726 
727  {
729 
730  Scheduler::Event event;
731  event.impl = id.PeekEventImpl ();
732  event.key.m_ts = id.GetTs ();
733  event.key.m_context = id.GetContext ();
734  event.key.m_uid = id.GetUid ();
735 
736  m_events->Remove (event);
738  event.impl->Cancel ();
739  event.impl->Unref ();
740  }
741 }
742 
743 void
745 {
746  if (IsExpired (id) == false)
747  {
748  id.PeekEventImpl ()->Cancel ();
749  }
750 }
751 
752 bool
754 {
755  if (ev.GetUid () == 2)
756  {
757  if (ev.PeekEventImpl () == 0 ||
758  ev.PeekEventImpl ()->IsCancelled ())
759  {
760  return true;
761  }
762  // destroy events.
763  for (DestroyEvents::const_iterator i = m_destroyEvents.begin ();
764  i != m_destroyEvents.end (); i++)
765  {
766  if (*i == ev)
767  {
768  return false;
769  }
770  }
771  return true;
772  }
773 
774  //
775  // If the time of the event is less than the current timestamp of the
776  // simulator, the simulator has gone past the invocation time of the
777  // event, so the statement ev.GetTs () < m_currentTs does mean that
778  // the event has been fired even in realtime mode.
779  //
780  // The same is true for the next line involving the m_currentUid.
781  //
782  if (ev.PeekEventImpl () == 0 ||
783  ev.GetTs () < m_currentTs ||
784  (ev.GetTs () == m_currentTs && ev.GetUid () <= m_currentUid) ||
785  ev.PeekEventImpl ()->IsCancelled ())
786  {
787  return true;
788  }
789  else
790  {
791  return false;
792  }
793 }
794 
795 Time
797 {
800  return TimeStep (0x7fffffffffffffffLL);
801 }
802 
803 // System ID for non-distributed simulation is always zero
804 uint32_t
806 {
807  return 0;
808 }
809 
810 uint32_t
812 {
813  return m_currentContext;
814 }
815 
816 void
818 {
819  NS_LOG_FUNCTION (this << mode);
820  m_synchronizationMode = mode;
821 }
822 
825 {
826  NS_LOG_FUNCTION (this);
827  return m_synchronizationMode;
828 }
829 
830 void
832 {
833  NS_LOG_FUNCTION (this << limit);
834  m_hardLimit = limit;
835 }
836 
837 Time
839 {
840  NS_LOG_FUNCTION (this);
841  return m_hardLimit;
842 }
843 
844 } // namespace ns3
void ScheduleRealtimeNowWithContext(uint32_t context, EventImpl *event)
void SetSynchronizationMode(RealtimeSimulatorImpl::SynchronizationMode mode)
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
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 "...
Ptr< const AttributeChecker > MakeEnumChecker(int v1, std::string n1, int v2, std::string n2, int v3, std::string n3, int v4, std::string n4, int v5, std::string n5, int v6, std::string n6, int v7, std::string n7, int v8, std::string n8, int v9, std::string n9, int v10, std::string n10, int v11, std::string n11, int v12, std::string n12, int v13, std::string n13, int v14, std::string n14, int v15, std::string n15, int v16, std::string n16, int v17, std::string n17, int v18, std::string n18, int v19, std::string n19, int v20, std::string n20, int v21, std::string n21, int v22, std::string n22)
Definition: enum.cc:178
virtual EventId ScheduleNow(EventImpl *event)
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
virtual EventId Schedule(Time const &time, EventImpl *event)
Time TimeStep(uint64_t ts)
Definition: nstime.h:997
void ScheduleRealtimeNow(EventImpl *event)
static ThreadId Self(void)
Returns the current thread Id.
EventImpl * impl
Definition: scheduler.h:73
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
virtual Time GetMaximumSimulationTime(void) const
Time m_hardLimit
The maximum allowable drift from real-time in SYNC_HARD_LIMIT mode.
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
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
SynchronizationMode m_synchronizationMode
The policy to use if the simulation cannot keep synchronized to real-time.
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
void ScheduleRealtimeWithContext(uint32_t context, Time const &time, EventImpl *event)
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
virtual EventId ScheduleDestroy(EventImpl *event)
virtual void ScheduleWithContext(uint32_t context, Time const &time, EventImpl *event)
RealtimeSimulatorImpl::SynchronizationMode GetSynchronizationMode(void) const
Make a best effort to keep synced to real-time.
hold variables of type 'enum'
Definition: enum.h:37
hold objects of type ns3::Time
Definition: nstime.h:1008
virtual Time Now(void) const
Return the "current simulation time".
virtual void Run(void)
Run the simulation until one of:
Ptr< Object > Create(void) const
A class which provides a simple way to implement a Critical Section.
Definition: system-mutex.h:109
virtual void Destroy()
This method is typically invoked at the end of a simulation to avoid false-positive reports by a leak...
void Unref(void) const
Decrement the reference count.
virtual void Remove(const EventId &ev)
Remove an event from the event list.
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 void Cancel(const EventId &ev)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
SynchronizationMode
Enumeration of the types of packets supported in the class.
virtual Time GetDelayLeft(const EventId &id) const
virtual uint32_t GetSystemId(void) const
int64_t GetTimeStep(void) const
Definition: nstime.h:354
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Definition: enum.h:118
static bool Equals(ThreadId id)
Compares an TharedId with the current ThreadId .
virtual bool IsExpired(const EventId &ev) const
This method has O(1) complexity.
#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 void SetScheduler(ObjectFactory schedulerFactory)
instantiate subclasses of ns3::Object.
a simulation event
Definition: event-impl.h:39
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
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:441
virtual uint32_t GetContext(void) const
virtual void Stop(void)
If an event invokes this method, it will be the last event scheduled by the Simulator::Run method bef...
void ScheduleRealtime(Time const &time, EventImpl *event)
virtual bool IsFinished(void) const
If there are no more events lefts to be scheduled, or if simulation time has already reached the "sto...
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.