19 #include "simulator.h"
20 #include "realtime-simulator-impl.h"
21 #include "wall-clock-synchronizer.h"
22 #include "scheduler.h"
23 #include "event-impl.h"
24 #include "synchronizer.h"
29 #include "fatal-error.h"
31 #include "system-mutex.h"
46 NS_OBJECT_ENSURE_REGISTERED (RealtimeSimulatorImpl);
49 RealtimeSimulatorImpl::GetTypeId (
void)
51 static TypeId tid = TypeId (
"ns3::RealtimeSimulatorImpl")
52 .SetParent<SimulatorImpl> ()
53 .AddConstructor<RealtimeSimulatorImpl> ()
54 .AddAttribute (
"SynchronizationMode",
55 "What to do if the simulation cannot keep up with real time.",
56 EnumValue (SYNC_BEST_EFFORT),
57 MakeEnumAccessor (&RealtimeSimulatorImpl::SetSynchronizationMode),
58 MakeEnumChecker (SYNC_BEST_EFFORT,
"BestEffort",
60 .AddAttribute (
"HardLimit",
61 "Maximum acceptable real-time jitter (used in conjunction with SynchronizationMode=HardLimit)",
70 RealtimeSimulatorImpl::RealtimeSimulatorImpl ()
84 m_currentContext = 0xffffffff;
85 m_unscheduledEvents = 0;
91 m_synchronizer = CreateObject<WallClockSynchronizer> ();
94 RealtimeSimulatorImpl::~RealtimeSimulatorImpl ()
103 while (!m_events->IsEmpty ())
126 while (m_destroyEvents.empty () ==
false)
129 m_destroyEvents.pop_front ();
131 if (ev->IsCancelled () ==
false)
150 while (m_events->IsEmpty () ==
false)
153 scheduler->Insert (next);
156 m_events = scheduler;
161 RealtimeSimulatorImpl::ProcessOneEvent (
void)
185 uint64_t tsDelay = 0;
215 "RealtimeSimulatorImpl::ProcessOneEvent (): Synchronizer reports not Realtime ()");
224 tsNow = m_synchronizer->GetCurrentRealtime ();
242 tsDelay = tsNext - tsNow;
252 m_synchronizer->SetCondition (
false);
289 if (m_synchronizer->Synchronize (tsNow, tsDelay))
311 Scheduler::Event next;
314 CriticalSection cs (m_mutex);
323 "RealtimeSimulatorImpl::ProcessOneEvent(): event queue is empty");
324 next = m_events->RemoveNext ();
325 m_unscheduledEvents--;
333 "RealtimeSimulatorImpl::ProcessOneEvent(): "
334 "next.GetTs() earlier than m_currentTs (list order error)");
342 m_currentTs = next.key.m_ts;
343 m_currentContext = next.key.m_context;
344 m_currentUid = next.key.m_uid;
357 uint64_t tsFinal = m_synchronizer->GetCurrentRealtime ();
360 if (tsFinal >= m_currentTs)
362 tsJitter = tsFinal - m_currentTs;
366 tsJitter = m_currentTs - tsFinal;
372 "Hard real-time limit exceeded (jitter = " << tsJitter <<
")");
382 EventImpl *
event = next.impl;
383 m_synchronizer->EventStart ();
385 m_synchronizer->EventEnd ();
395 rc = m_events->IsEmpty () || m_stop;
405 RealtimeSimulatorImpl::NextTs (
void)
const
408 "RealtimeSimulatorImpl::NextTs(): event queue is empty");
419 "RealtimeSimulatorImpl::Run(): Simulator already running");
426 m_synchronizer->SetOrigin (m_currentTs);
430 uint64_t tsDelay = 1000000000;
434 bool process =
false;
438 if (!m_events->IsEmpty ())
445 tsNow = m_synchronizer->GetCurrentRealtime ();
452 tsNow = m_synchronizer->Synchronize (tsNow, tsDelay);
468 NS_ASSERT_MSG (m_events->IsEmpty () ==
false || m_unscheduledEvents == 0,
469 "RealtimeSimulatorImpl::Run(): Empty queue and unprocessed events");
476 RealtimeSimulatorImpl::Running (
void)
const
482 RealtimeSimulatorImpl::Realtime (
void)
const
484 return m_synchronizer->Realtime ();
520 NS_ASSERT_MSG (tAbsolute >= TimeStep (m_currentTs),
"RealtimeSimulatorImpl::Schedule(): time < m_currentTs");
524 ev.key.m_uid = m_uid;
526 m_unscheduledEvents++;
527 m_events->Insert (ev);
528 m_synchronizer->Signal ();
531 return EventId (impl, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
553 ts = m_running ? m_synchronizer->GetCurrentRealtime () : m_currentTs;
557 NS_ASSERT_MSG (ts >= m_currentTs,
"RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs");
561 ev.key.m_context = context;
562 ev.key.m_uid = m_uid;
564 m_unscheduledEvents++;
565 m_events->Insert (ev);
566 m_synchronizer->Signal ();
579 ev.key.m_ts = m_currentTs;
581 ev.key.m_uid = m_uid;
583 m_unscheduledEvents++;
584 m_events->Insert (ev);
585 m_synchronizer->Signal ();
588 return EventId (impl, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
594 return TimeStep (m_currentTs);
601 RealtimeSimulatorImpl::ScheduleRealtimeWithContext (uint32_t context,
Time const &time,
EventImpl *impl)
608 uint64_t ts = m_synchronizer->GetCurrentRealtime () + time.
GetTimeStep ();
609 NS_ASSERT_MSG (ts >= m_currentTs,
"RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs");
613 ev.key.m_uid = m_uid;
615 m_unscheduledEvents++;
616 m_events->Insert (ev);
617 m_synchronizer->Signal ();
622 RealtimeSimulatorImpl::ScheduleRealtime (Time
const &time, EventImpl *impl)
625 ScheduleRealtimeWithContext (
GetContext (), time, impl);
629 RealtimeSimulatorImpl::ScheduleRealtimeNowWithContext (uint32_t context, EventImpl *impl)
633 CriticalSection cs (m_mutex);
639 uint64_t ts = m_running ? m_synchronizer->GetCurrentRealtime () : m_currentTs;
641 "RealtimeSimulatorImpl::ScheduleRealtimeNowWithContext(): schedule for time < m_currentTs");
645 ev.key.m_uid = m_uid;
646 ev.key.m_context = context;
648 m_unscheduledEvents++;
649 m_events->Insert (ev);
650 m_synchronizer->Signal ();
655 RealtimeSimulatorImpl::ScheduleRealtimeNow (EventImpl *impl)
658 ScheduleRealtimeNowWithContext (
GetContext (), impl);
662 RealtimeSimulatorImpl::RealtimeNow (
void)
const
664 return TimeStep (m_synchronizer->GetCurrentRealtime ());
682 m_destroyEvents.push_back (
id);
701 return TimeStep (
id.GetTs () - m_currentTs);
707 if (
id.GetUid () == 2)
710 for (DestroyEvents::iterator i = m_destroyEvents.begin ();
711 i != m_destroyEvents.end ();
716 m_destroyEvents.erase (i);
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 ();
736 m_events->Remove (event);
737 m_unscheduledEvents--;
738 event.impl->Cancel ();
739 event.impl->Unref ();
748 id.PeekEventImpl ()->Cancel ();
755 if (ev.GetUid () == 2)
757 if (ev.PeekEventImpl () == 0 ||
763 for (DestroyEvents::const_iterator i = m_destroyEvents.begin ();
764 i != m_destroyEvents.end (); i++)
782 if (ev.PeekEventImpl () == 0 ||
783 ev.GetTs () < m_currentTs ||
784 (ev.GetTs () == m_currentTs && ev.GetUid () <= m_currentUid) ||
800 return TimeStep (0x7fffffffffffffffLL);
813 return m_currentContext;
817 RealtimeSimulatorImpl::SetSynchronizationMode (
enum SynchronizationMode mode)
824 RealtimeSimulatorImpl::GetSynchronizationMode (
void)
const
831 RealtimeSimulatorImpl::SetHardLimit (Time limit)
838 RealtimeSimulatorImpl::GetHardLimit (
void)
const
smart pointer class similar to boost::intrusive_ptr
bool IsPositive(void) const
#define NS_LOG_FUNCTION(parameters)
virtual EventId ScheduleNow(EventImpl *event)
virtual EventId Schedule(Time const &time, EventImpl *event)
#define NS_LOG_COMPONENT_DEFINE(name)
virtual Time GetMaximumSimulationTime(void) const
virtual void DoDispose(void)
SynchronizationMode m_synchronizationMode
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
virtual void DoDispose(void)
virtual EventId ScheduleDestroy(EventImpl *event)
virtual void ScheduleWithContext(uint32_t context, Time const &time, EventImpl *event)
#define NS_FATAL_ERROR(msg)
fatal error handling
virtual Time Now(void) const
Ptr< Object > Create(void) const
A class which provides a simple way to implement a Critical Section.
virtual void Remove(const EventId &ev)
#define NS_LOG_LOGIC(msg)
virtual void Cancel(const EventId &ev)
static bool Equals(ThreadId id)
Compares an TharedId with the current ThreadId .
virtual Time GetDelayLeft(const EventId &id) const
virtual uint32_t GetSystemId(void) const
int64_t GetTimeStep(void) const
virtual bool IsExpired(const EventId &ev) const
#define NS_ASSERT_MSG(condition, message)
virtual void SetScheduler(ObjectFactory schedulerFactory)
instantiate subclasses of ns3::Object.
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
an identifier for simulation events.
virtual uint32_t GetContext(void) const
static ThreadId Self(void)
Returns the current thread Id.
virtual bool IsFinished(void) const