diff --git a/src/node/channel.h b/src/node/channel.h index 67fd082a9..b0c2b6d6b 100644 --- a/src/node/channel.h +++ b/src/node/channel.h @@ -36,6 +36,9 @@ class NetDevice; * * A channel is a logical path over which information flows. The path can * be as simple as a short piece of wire, or as complicated as space-time. + * + * Subclasses must use Simulator::ScheduleWithContext to correctly update + * event contexts when scheduling an event from one node to another one. */ class Channel : public Object { diff --git a/src/simulator/default-simulator-impl.cc b/src/simulator/default-simulator-impl.cc index 39506737d..22f79d4e0 100644 --- a/src/simulator/default-simulator-impl.cc +++ b/src/simulator/default-simulator-impl.cc @@ -53,10 +53,11 @@ DefaultSimulatorImpl::DefaultSimulatorImpl () // uid 0 is "invalid" events // uid 1 is "now" events // uid 2 is "destroy" events - m_uid = 4; + m_uid = 4; // before ::Run is entered, the m_currentUid will be zero m_currentUid = 0; m_currentTs = 0; + m_currentContext = 0xffffffff; m_unscheduledEvents = 0; } @@ -107,10 +108,11 @@ DefaultSimulatorImpl::ProcessOneEvent (void) Scheduler::Event next = m_events->RemoveNext (); NS_ASSERT (next.key.m_ts >= m_currentTs); - --m_unscheduledEvents; + m_unscheduledEvents--; NS_LOG_LOGIC ("handle " << next.key.m_ts); m_currentTs = next.key.m_ts; + m_currentContext = next.key.m_context; m_currentUid = next.key.m_uid; next.impl->Invoke (); next.impl->Unref (); @@ -162,6 +164,11 @@ DefaultSimulatorImpl::Stop (void) m_stop = true; } +void +DefaultSimulatorImpl::Stop (Time const &time) +{ + Simulator::Schedule (time, &Simulator::Stop); +} // // Schedule an event for a _relative_ time in the future. @@ -169,18 +176,34 @@ DefaultSimulatorImpl::Stop (void) EventId DefaultSimulatorImpl::Schedule (Time const &time, EventImpl *event) { - Time tAbsolute = time + Now(); + Time tAbsolute = time + TimeStep (m_currentTs); NS_ASSERT (tAbsolute.IsPositive ()); NS_ASSERT (tAbsolute >= TimeStep (m_currentTs)); Scheduler::Event ev; ev.impl = event; ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep (); + ev.key.m_context = GetContext (); ev.key.m_uid = m_uid; m_uid++; - ++m_unscheduledEvents; + m_unscheduledEvents++; + m_events->Insert (ev); + return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid); +} + +void +DefaultSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event) +{ + NS_LOG_FUNCTION (this << context << time.GetTimeStep () << m_currentTs << event); + + Scheduler::Event ev; + ev.impl = event; + ev.key.m_ts = m_currentTs + time.GetTimeStep (); + ev.key.m_context = context; + ev.key.m_uid = m_uid; + m_uid++; + m_unscheduledEvents++; m_events->Insert (ev); - return EventId (event, ev.key.m_ts, ev.key.m_uid); } EventId @@ -189,17 +212,18 @@ DefaultSimulatorImpl::ScheduleNow (EventImpl *event) Scheduler::Event ev; ev.impl = event; ev.key.m_ts = m_currentTs; + ev.key.m_context = GetContext (); ev.key.m_uid = m_uid; m_uid++; - ++m_unscheduledEvents; + m_unscheduledEvents++; m_events->Insert (ev); - return EventId (event, ev.key.m_ts, ev.key.m_uid); + return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid); } EventId DefaultSimulatorImpl::ScheduleDestroy (EventImpl *event) { - EventId id (Ptr (event, false), m_currentTs, 2); + EventId id (Ptr (event, false), m_currentTs, 0xffffffff, 2); m_destroyEvents.push_back (id); m_uid++; return id; @@ -247,13 +271,14 @@ DefaultSimulatorImpl::Remove (const EventId &id) Scheduler::Event event; event.impl = id.PeekEventImpl (); event.key.m_ts = id.GetTs (); + event.key.m_context = id.GetContext (); event.key.m_uid = id.GetUid (); m_events->Remove (event); event.impl->Cancel (); // whenever we remove an event from the event list, we have to unref it. event.impl->Unref (); - --m_unscheduledEvents; + m_unscheduledEvents--; } void @@ -307,6 +332,12 @@ DefaultSimulatorImpl::GetMaximumSimulationTime (void) const return TimeStep (0x7fffffffffffffffLL); } +uint32_t +DefaultSimulatorImpl::GetContext (void) const +{ + return m_currentContext; +} + } // namespace ns3 diff --git a/src/simulator/default-simulator-impl.h b/src/simulator/default-simulator-impl.h index c5156078b..db3b25ee8 100644 --- a/src/simulator/default-simulator-impl.h +++ b/src/simulator/default-simulator-impl.h @@ -26,14 +26,12 @@ #include "event-impl.h" #include "ns3/ptr.h" -#include "ns3/assert.h" -#include "ns3/log.h" #include namespace ns3 { - class DefaultSimulatorImpl : public SimulatorImpl +class DefaultSimulatorImpl : public SimulatorImpl { public: static TypeId GetTypeId (void); @@ -45,7 +43,9 @@ public: virtual bool IsFinished (void) const; virtual Time Next (void) const; virtual void Stop (void); + virtual void Stop (Time const &time); virtual EventId Schedule (Time const &time, EventImpl *event); + virtual void ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event); virtual EventId ScheduleNow (EventImpl *event); virtual EventId ScheduleDestroy (EventImpl *event); virtual void Remove (const EventId &ev); @@ -57,18 +57,20 @@ public: virtual Time GetDelayLeft (const EventId &id) const; virtual Time GetMaximumSimulationTime (void) const; virtual void SetScheduler (ObjectFactory schedulerFactory); + virtual uint32_t GetContext (void) const; private: void ProcessOneEvent (void); uint64_t NextTs (void) const; - typedef std::list DestroyEvents; + DestroyEvents m_destroyEvents; bool m_stop; Ptr m_events; uint32_t m_uid; uint32_t m_currentUid; uint64_t m_currentTs; + uint32_t m_currentContext; // number of events that have been inserted but not yet scheduled, // not counting the "destroy" events; this is used for validation int m_unscheduledEvents; diff --git a/src/simulator/event-id.cc b/src/simulator/event-id.cc index 78d476f94..a8258cfd6 100644 --- a/src/simulator/event-id.cc +++ b/src/simulator/event-id.cc @@ -26,12 +26,14 @@ namespace ns3 { EventId::EventId () : m_eventImpl (0), m_ts (0), + m_context (0), m_uid (0) {} -EventId::EventId (const Ptr &impl, uint64_t ts, uint32_t uid) +EventId::EventId (const Ptr &impl, uint64_t ts, uint32_t context, uint32_t uid) : m_eventImpl (impl), m_ts (ts), + m_context (context), m_uid (uid) {} void @@ -60,6 +62,11 @@ EventId::GetTs (void) const return m_ts; } uint32_t +EventId::GetContext (void) const +{ + return m_context; +} +uint32_t EventId::GetUid (void) const { return m_uid; @@ -69,6 +76,7 @@ bool operator == (const EventId &a, const EventId &b) { return a.m_uid == b.m_uid && + a.m_context == b.m_context && a.m_ts == b.m_ts && a.m_eventImpl == b.m_eventImpl; } diff --git a/src/simulator/event-id.h b/src/simulator/event-id.h index 2269646de..a28acbba6 100644 --- a/src/simulator/event-id.h +++ b/src/simulator/event-id.h @@ -47,7 +47,7 @@ class EventId { public: EventId (); // internal. - EventId (const Ptr &impl, uint64_t ts, uint32_t uid); + EventId (const Ptr &impl, uint64_t ts, uint32_t context, uint32_t uid); /** * This method is syntactic sugar for the ns3::Simulator::cancel * method. @@ -72,11 +72,13 @@ public: */ EventImpl *PeekEventImpl (void) const; uint64_t GetTs (void) const; + uint32_t GetContext (void) const; uint32_t GetUid (void) const; private: friend bool operator == (const EventId &a, const EventId &b); Ptr m_eventImpl; uint64_t m_ts; + uint32_t m_context; uint32_t m_uid; }; diff --git a/src/simulator/realtime-simulator-impl.cc b/src/simulator/realtime-simulator-impl.cc index ccbd2fa4f..8b6cc68c3 100644 --- a/src/simulator/realtime-simulator-impl.cc +++ b/src/simulator/realtime-simulator-impl.cc @@ -77,6 +77,7 @@ RealtimeSimulatorImpl::RealtimeSimulatorImpl () // before ::Run is entered, the m_currentUid will be zero m_currentUid = 0; m_currentTs = 0; + m_currentContext = 0xffffffff; m_unscheduledEvents = 0; // Be very careful not to do anything that would cause a change or assignment @@ -309,7 +310,7 @@ RealtimeSimulatorImpl::ProcessOneEvent (void) NS_ASSERT_MSG (m_events->IsEmpty () == false, "RealtimeSimulatorImpl::ProcessOneEvent(): event queue is empty"); next = m_events->RemoveNext (); - --m_unscheduledEvents; + m_unscheduledEvents--; // // We cannot make any assumption that "next" is the same event we originally waited @@ -327,6 +328,7 @@ RealtimeSimulatorImpl::ProcessOneEvent (void) // is frozen until the next event is executed. // m_currentTs = next.key.m_ts; + m_currentContext = next.key.m_context; m_currentUid = next.key.m_uid; // @@ -506,10 +508,11 @@ RealtimeSimulatorImpl::RunOneEvent (void) Scheduler::Event next = m_events->RemoveNext (); NS_ASSERT (next.key.m_ts >= m_currentTs); - --m_unscheduledEvents; + m_unscheduledEvents--; NS_LOG_LOGIC ("handle " << next.key.m_ts); m_currentTs = next.key.m_ts; + m_currentContext = next.key.m_context; m_currentUid = next.key.m_ts; event = next.impl; } @@ -524,6 +527,12 @@ RealtimeSimulatorImpl::Stop (void) m_stop = true; } +void +RealtimeSimulatorImpl::Stop (Time const &time) +{ + Simulator::Schedule (time, &Simulator::Stop); +} + // // Schedule an event for a _relative_ time in the future. // @@ -546,14 +555,38 @@ RealtimeSimulatorImpl::Schedule (Time const &time, EventImpl *impl) NS_ASSERT_MSG (tAbsolute >= TimeStep (m_currentTs), "RealtimeSimulatorImpl::Schedule(): time < m_currentTs"); ev.impl = impl; ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep (); + ev.key.m_context = GetContext (); ev.key.m_uid = m_uid; m_uid++; - ++m_unscheduledEvents; + m_unscheduledEvents++; m_events->Insert (ev); m_synchronizer->Signal (); } - return EventId (impl, ev.key.m_ts, ev.key.m_uid); + return EventId (impl, ev.key.m_ts, ev.key.m_context, ev.key.m_uid); +} + +void +RealtimeSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &time, EventImpl *impl) +{ + NS_LOG_FUNCTION (time << impl); + + { + CriticalSection cs (m_mutex); + uint64_t ts; + + ts = m_currentTs + time.GetTimeStep (); + NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs"); + Scheduler::Event ev; + ev.impl = impl; + ev.key.m_ts = ts; + ev.key.m_context = context; + ev.key.m_uid = m_uid; + m_uid++; + m_unscheduledEvents++; + m_events->Insert (ev); + m_synchronizer->Signal (); + } } EventId @@ -566,14 +599,15 @@ RealtimeSimulatorImpl::ScheduleNow (EventImpl *impl) ev.impl = impl; ev.key.m_ts = m_currentTs; + ev.key.m_context = GetContext (); ev.key.m_uid = m_uid; m_uid++; - ++m_unscheduledEvents; + m_unscheduledEvents++; m_events->Insert (ev); m_synchronizer->Signal (); } - return EventId (impl, ev.key.m_ts, ev.key.m_uid); + return EventId (impl, ev.key.m_ts, ev.key.m_context, ev.key.m_uid); } Time @@ -601,7 +635,7 @@ RealtimeSimulatorImpl::ScheduleRealtime (Time const &time, EventImpl *impl) ev.key.m_ts = ts; ev.key.m_uid = m_uid; m_uid++; - ++m_unscheduledEvents; + m_unscheduledEvents++; m_events->Insert (ev); m_synchronizer->Signal (); } @@ -626,7 +660,7 @@ RealtimeSimulatorImpl::ScheduleRealtimeNow (EventImpl *impl) ev.key.m_ts = ts; ev.key.m_uid = m_uid; m_uid++; - ++m_unscheduledEvents; + m_unscheduledEvents++; m_events->Insert (ev); m_synchronizer->Signal (); } @@ -652,7 +686,7 @@ RealtimeSimulatorImpl::ScheduleDestroy (EventImpl *impl) // overridden by the uid of 2 which identifies this as an event to be // executed at Simulator::Destroy time. // - id = EventId (Ptr (impl, false), m_currentTs, 2); + id = EventId (Ptr (impl, false), m_currentTs, 0xffffffff, 2); m_destroyEvents.push_back (id); m_uid++; } @@ -704,10 +738,11 @@ RealtimeSimulatorImpl::Remove (const EventId &id) Scheduler::Event event; event.impl = id.PeekEventImpl (); event.key.m_ts = id.GetTs (); + event.key.m_context = id.GetContext (); event.key.m_uid = id.GetUid (); m_events->Remove (event); - --m_unscheduledEvents; + m_unscheduledEvents--; event.impl->Cancel (); event.impl->Unref (); } @@ -773,6 +808,12 @@ RealtimeSimulatorImpl::GetMaximumSimulationTime (void) const return TimeStep (0x7fffffffffffffffLL); } +uint32_t +RealtimeSimulatorImpl::GetContext (void) const +{ + return m_currentContext; +} + void RealtimeSimulatorImpl::SetSynchronizationMode (enum SynchronizationMode mode) { diff --git a/src/simulator/realtime-simulator-impl.h b/src/simulator/realtime-simulator-impl.h index 832919af1..b7ff62476 100644 --- a/src/simulator/realtime-simulator-impl.h +++ b/src/simulator/realtime-simulator-impl.h @@ -55,7 +55,9 @@ public: virtual bool IsFinished (void) const; virtual Time Next (void) const; virtual void Stop (void); + virtual void Stop (Time const &time); virtual EventId Schedule (Time const &time, EventImpl *event); + virtual void ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event); virtual EventId ScheduleNow (EventImpl *event); virtual EventId ScheduleDestroy (EventImpl *event); virtual void Remove (const EventId &ev); @@ -67,6 +69,7 @@ public: virtual Time GetDelayLeft (const EventId &id) const; virtual Time GetMaximumSimulationTime (void) const; virtual void SetScheduler (ObjectFactory schedulerFactory); + virtual uint32_t GetContext (void) const; void ScheduleRealtime (Time const &time, EventImpl *event); void ScheduleRealtimeNow (EventImpl *event); @@ -96,6 +99,7 @@ private: uint32_t m_uid; uint32_t m_currentUid; uint64_t m_currentTs; + uint32_t m_currentContext; mutable SystemMutex m_mutex; diff --git a/src/simulator/scheduler.h b/src/simulator/scheduler.h index 394987f7c..3ed2ab0ba 100644 --- a/src/simulator/scheduler.h +++ b/src/simulator/scheduler.h @@ -56,8 +56,9 @@ class Scheduler : public Object static TypeId GetTypeId (void); struct EventKey { - uint64_t m_ts; - uint32_t m_uid; + uint64_t m_ts; + uint32_t m_uid; + uint32_t m_context; }; struct Event { EventImpl *impl; diff --git a/src/simulator/simulator-impl.h b/src/simulator/simulator-impl.h index 166905a9d..67664ee0b 100644 --- a/src/simulator/simulator-impl.h +++ b/src/simulator/simulator-impl.h @@ -39,7 +39,9 @@ public: virtual bool IsFinished (void) const = 0; virtual Time Next (void) const = 0; virtual void Stop (void) = 0; + virtual void Stop (Time const &time) = 0; virtual EventId Schedule (Time const &time, EventImpl *event) = 0; + virtual void ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event) = 0; virtual EventId ScheduleNow (EventImpl *event) = 0; virtual EventId ScheduleDestroy (EventImpl *event) = 0; virtual void Remove (const EventId &ev) = 0; @@ -51,6 +53,7 @@ public: virtual Time GetDelayLeft (const EventId &id) const = 0; virtual Time GetMaximumSimulationTime (void) const = 0; virtual void SetScheduler (ObjectFactory schedulerFactory) = 0; + virtual uint32_t GetContext (void) const = 0; }; } // namespace ns3 diff --git a/src/simulator/simulator.cc b/src/simulator/simulator.cc index dda4f9d63..ae00f5f12 100644 --- a/src/simulator/simulator.cc +++ b/src/simulator/simulator.cc @@ -20,10 +20,6 @@ #include "ns3/core-config.h" #include "simulator.h" #include "simulator-impl.h" -#include "default-simulator-impl.h" -#ifdef HAVE_PTHREAD_H -# include "realtime-simulator-impl.h" -#endif #include "scheduler.h" #include "map-scheduler.h" #include "event-impl.h" @@ -71,19 +67,19 @@ TimePrinter (std::ostream &os) #endif /* NS3_LOG_ENABLE */ -static Ptr *PeekImpl (void) +static SimulatorImpl **PeekImpl (void) { - static Ptr impl = 0; + static SimulatorImpl *impl = 0; return &impl; } static SimulatorImpl * GetImpl (void) { - Ptr &impl = *PeekImpl (); + SimulatorImpl **pimpl = PeekImpl (); /* Please, don't include any calls to logging macros in this function * or pay the price, that is, stack explosions. */ - if (impl == 0) + if (*pimpl == 0) { { ObjectFactory factory; @@ -91,14 +87,14 @@ static SimulatorImpl * GetImpl (void) g_simTypeImpl.GetValue (s); factory.SetTypeId (s.Get ()); - impl = factory.Create (); + *pimpl = GetPointer (factory.Create ()); } { ObjectFactory factory; StringValue s; g_schedTypeImpl.GetValue (s); factory.SetTypeId (s.Get ()); - impl->SetScheduler (factory); + (*pimpl)->SetScheduler (factory); } // @@ -110,7 +106,7 @@ static SimulatorImpl * GetImpl (void) // LogSetTimePrinter (&TimePrinter); } - return PeekPointer (impl); + return *pimpl; } void @@ -118,8 +114,8 @@ Simulator::Destroy (void) { NS_LOG_FUNCTION_NOARGS (); - Ptr &impl = *PeekImpl (); - if (impl == 0) + SimulatorImpl **pimpl = PeekImpl (); + if (*pimpl == 0) { return; } @@ -129,8 +125,9 @@ Simulator::Destroy (void) * the stack explodes. */ LogSetTimePrinter (0); - impl->Destroy (); - impl = 0; + (*pimpl)->Destroy (); + (*pimpl)->Unref (); + *pimpl = 0; } void @@ -179,7 +176,7 @@ void Simulator::Stop (Time const &time) { NS_LOG_FUNCTION (time); - Simulator::Schedule (time, &Simulator::Stop); + GetImpl ()->Stop (time); } Time @@ -205,6 +202,13 @@ Simulator::Schedule (Time const &time, const Ptr &ev) return DoSchedule (time, GetPointer (ev)); } +void +Simulator::ScheduleWithContext (uint32_t context, Time const &time, const Ptr &ev) +{ + NS_LOG_FUNCTION (time << context << ev); + return DoScheduleWithContext (context, time, GetPointer (ev)); +} + EventId Simulator::ScheduleNow (const Ptr &ev) { @@ -223,6 +227,11 @@ Simulator::DoSchedule (Time const &time, EventImpl *impl) { return GetImpl ()->Schedule (time, impl); } +void +Simulator::DoScheduleWithContext (uint32_t context, Time const &time, EventImpl *impl) +{ + return GetImpl ()->ScheduleWithContext (context, time, impl); +} EventId Simulator::DoScheduleNow (EventImpl *impl) { @@ -242,6 +251,13 @@ Simulator::Schedule (Time const &time, void (*f) (void)) return DoSchedule (time, MakeEvent (f)); } +void +Simulator::ScheduleWithContext (uint32_t context, Time const &time, void (*f) (void)) +{ + NS_LOG_FUNCTION (time << context << f); + return DoScheduleWithContext (context, time, MakeEvent (f)); +} + EventId Simulator::ScheduleNow (void (*f) (void)) { @@ -290,6 +306,13 @@ Simulator::GetMaximumSimulationTime (void) return GetImpl ()->GetMaximumSimulationTime (); } +uint32_t +Simulator::GetContext (void) +{ + NS_LOG_FUNCTION_NOARGS (); + return GetImpl ()->GetContext (); +} + void Simulator::SetImplementation (Ptr impl) { @@ -297,7 +320,7 @@ Simulator::SetImplementation (Ptr impl) { NS_FATAL_ERROR ("It is not possible to set the implementation after calling any Simulator:: function. Call Simulator::SetImplementation earlier or after Simulator::Destroy."); } - *PeekImpl () = impl; + *PeekImpl () = GetPointer (impl); // Set the default scheduler ObjectFactory factory; StringValue s; diff --git a/src/simulator/simulator.h b/src/simulator/simulator.h index ec02182fa..cb7e825f4 100644 --- a/src/simulator/simulator.h +++ b/src/simulator/simulator.h @@ -283,6 +283,145 @@ public: typename T1, typename T2, typename T3, typename T4, typename T5> static EventId Schedule (Time const &time, void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); + /** + * Schedule an event with the given context. + * A context of 0xffffffff means no context is specified. + * + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param mem_ptr member method pointer to invoke + * @param obj the object on which to invoke the member method + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param mem_ptr member method pointer to invoke + * @param obj the object on which to invoke the member method + * @param a1 the first argument to pass to the invoked method + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, T1 a1); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param mem_ptr member method pointer to invoke + * @param obj the object on which to invoke the member method + * @param a1 the first argument to pass to the invoked method + * @param a2 the second argument to pass to the invoked method + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param mem_ptr member method pointer to invoke + * @param obj the object on which to invoke the member method + * @param a1 the first argument to pass to the invoked method + * @param a2 the second argument to pass to the invoked method + * @param a3 the third argument to pass to the invoked method + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param mem_ptr member method pointer to invoke + * @param obj the object on which to invoke the member method + * @param a1 the first argument to pass to the invoked method + * @param a2 the second argument to pass to the invoked method + * @param a3 the third argument to pass to the invoked method + * @param a4 the fourth argument to pass to the invoked method + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param mem_ptr member method pointer to invoke + * @param obj the object on which to invoke the member method + * @param a1 the first argument to pass to the invoked method + * @param a2 the second argument to pass to the invoked method + * @param a3 the third argument to pass to the invoked method + * @param a4 the fourth argument to pass to the invoked method + * @param a5 the fifth argument to pass to the invoked method + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, + T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param f the function to invoke + */ + static void ScheduleWithContext (uint32_t context, Time const &time, void (*f) (void)); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param f the function to invoke + * @param a1 the first argument to pass to the function to invoke + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1), T1 a1); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param f the function to invoke + * @param a1 the first argument to pass to the function to invoke + * @param a2 the second argument to pass to the function to invoke + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1,U2), T1 a1, T2 a2); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param f the function to invoke + * @param a1 the first argument to pass to the function to invoke + * @param a2 the second argument to pass to the function to invoke + * @param a3 the third argument to pass to the function to invoke + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param f the function to invoke + * @param a1 the first argument to pass to the function to invoke + * @param a2 the second argument to pass to the function to invoke + * @param a3 the third argument to pass to the function to invoke + * @param a4 the fourth argument to pass to the function to invoke + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4); + + /** + * @param time the relative expiration time of the event. + * @param context user-specified context parameter + * @param f the function to invoke + * @param a1 the first argument to pass to the function to invoke + * @param a2 the second argument to pass to the function to invoke + * @param a3 the third argument to pass to the function to invoke + * @param a4 the fourth argument to pass to the function to invoke + * @param a5 the fifth argument to pass to the function to invoke + */ + template + static void ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); + /** * Schedule an event to expire Now. All events scheduled to * to expire "Now" are scheduled FIFO, after all normal events @@ -588,6 +727,11 @@ public: */ static Time GetMaximumSimulationTime (void); + /** + * \returns the current simulation context + */ + static uint32_t GetContext (void); + /** * \param time delay until the event expires * \param event the event to schedule @@ -598,6 +742,17 @@ public: */ static EventId Schedule (Time const &time, const Ptr &event); + /** + * \param time delay until the event expires + * \param context event context + * \param event the event to schedule + * \returns a unique identifier for the newly-scheduled event. + * + * This method will be typically used by language bindings + * to delegate events to their own subclass of the EventImpl base class. + */ + static void ScheduleWithContext (uint32_t context, Time const &time, const Ptr &event); + /** * \param event the event to schedule * \returns a unique identifier for the newly-scheduled event. @@ -620,6 +775,7 @@ private: ~Simulator (); static EventId DoSchedule (Time const &time, EventImpl *event); + static void DoScheduleWithContext (uint32_t context, Time const &time, EventImpl *event); static EventId DoScheduleNow (EventImpl *event); static EventId DoScheduleDestroy (EventImpl *event); }; @@ -721,6 +877,86 @@ EventId Simulator::Schedule (Time const &time, void (*f) (U1,U2,U3,U4,U5), T1 a1 +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj) +{ + DoScheduleWithContext (context, time, MakeEvent (mem_ptr, obj)); +} + + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, T1 a1) +{ + return DoScheduleWithContext (context, time, MakeEvent (mem_ptr, obj, a1)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2) +{ + return DoScheduleWithContext (context, time, MakeEvent (mem_ptr, obj, a1, a2)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3) +{ + return DoScheduleWithContext (context, time, MakeEvent (mem_ptr, obj, a1, a2, a3)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) +{ + return DoScheduleWithContext (context, time, MakeEvent (mem_ptr, obj, a1, a2, a3, a4)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, MEM mem_ptr, OBJ obj, + T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) +{ + return DoScheduleWithContext (context, time, MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1), T1 a1) +{ + return DoScheduleWithContext (context, time, MakeEvent (f, a1)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1,U2), T1 a1, T2 a2) +{ + return DoScheduleWithContext (context, time, MakeEvent (f, a1, a2)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3) +{ + return DoScheduleWithContext (context, time, MakeEvent (f, a1, a2, a3)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4) +{ + return DoScheduleWithContext (context, time, MakeEvent (f, a1, a2, a3, a4)); +} + +template +void Simulator::ScheduleWithContext (uint32_t context, Time const &time, void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) +{ + return DoScheduleWithContext (context, time, MakeEvent (f, a1, a2, a3, a4, a5)); +} + + + + template EventId Simulator::ScheduleNow (MEM mem_ptr, OBJ obj)