don't use EventId in Schedulers: use Scheduler::Event instead.

This commit is contained in:
Mathieu Lacage
2008-10-15 13:05:33 +02:00
parent 253fecb82e
commit b4e442df4d
10 changed files with 170 additions and 201 deletions

View File

@@ -69,7 +69,8 @@ DefaultSimulatorImpl::~DefaultSimulatorImpl ()
{
while (!m_events->IsEmpty ())
{
EventId next = m_events->RemoveNext ();
Scheduler::Event next = m_events->RemoveNext ();
next.impl->Unref ();
}
m_events = 0;
}
@@ -96,7 +97,7 @@ DefaultSimulatorImpl::SetScheduler (Ptr<Scheduler> scheduler)
{
while (!m_events->IsEmpty ())
{
EventId next = m_events->RemoveNext ();
Scheduler::Event next = m_events->RemoveNext ();
scheduler->Insert (next);
}
}
@@ -113,16 +114,16 @@ DefaultSimulatorImpl::GetScheduler (void) const
void
DefaultSimulatorImpl::ProcessOneEvent (void)
{
EventId next = m_events->RemoveNext ();
Scheduler::Event next = m_events->RemoveNext ();
NS_ASSERT (next.GetTs () >= m_currentTs);
NS_ASSERT (next.key.m_ts >= m_currentTs);
--m_unscheduledEvents;
NS_LOG_LOGIC ("handle " << next.GetTs ());
m_currentTs = next.GetTs ();
m_currentUid = next.GetUid ();
EventImpl *event = next.PeekEventImpl ();
event->Invoke ();
NS_LOG_LOGIC ("handle " << next.key.m_ts);
m_currentTs = next.key.m_ts;
m_currentUid = next.key.m_uid;
next.impl->Invoke ();
next.impl->Unref ();
}
bool
@@ -135,8 +136,8 @@ uint64_t
DefaultSimulatorImpl::NextTs (void) const
{
NS_ASSERT (!m_events->IsEmpty ());
EventId id = m_events->PeekNext ();
return id.GetTs ();
Scheduler::Event ev = m_events->PeekNext ();
return ev.key.m_ts;
}
Time
@@ -190,22 +191,27 @@ DefaultSimulatorImpl::Schedule (Time const &time, const Ptr<EventImpl> &event)
NS_ASSERT (tAbsolute.IsPositive ());
NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
uint64_t ts = (uint64_t) tAbsolute.GetTimeStep ();
EventId id (event, ts, m_uid);
Scheduler::Event ev;
ev.impl = GetPointer (event);
ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
ev.key.m_uid = m_uid;
m_uid++;
++m_unscheduledEvents;
m_events->Insert (id);
return id;
m_events->Insert (ev);
return EventId (event, ev.key.m_ts, ev.key.m_uid);
}
EventId
DefaultSimulatorImpl::ScheduleNow (const Ptr<EventImpl> &event)
{
EventId id (event, m_currentTs, m_uid);
Scheduler::Event ev;
ev.impl = GetPointer (event);
ev.key.m_ts = m_currentTs;
ev.key.m_uid = m_uid;
m_uid++;
++m_unscheduledEvents;
m_events->Insert (id);
return id;
m_events->Insert (ev);
return EventId (event, ev.key.m_ts, ev.key.m_uid);
}
EventId
@@ -237,14 +243,14 @@ DefaultSimulatorImpl::GetDelayLeft (const EventId &id) const
}
void
DefaultSimulatorImpl::Remove (const EventId &ev)
DefaultSimulatorImpl::Remove (const EventId &id)
{
if (ev.GetUid () == 2)
if (id.GetUid () == 2)
{
// destroy events.
for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
{
if (*i == ev)
if (*i == id)
{
m_destroyEvents.erase (i);
break;
@@ -252,12 +258,18 @@ DefaultSimulatorImpl::Remove (const EventId &ev)
}
return;
}
if (IsExpired (ev))
if (IsExpired (id))
{
return;
}
m_events->Remove (ev);
Cancel (ev);
Scheduler::Event event;
event.impl = id.PeekEventImpl ();
event.key.m_ts = id.GetTs ();
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;
}
@@ -308,6 +320,6 @@ DefaultSimulatorImpl::GetMaximumSimulationTime (void) const
return TimeStep (0x7fffffffffffffffLL);
}
}; // namespace ns3
} // namespace ns3

View File

@@ -23,20 +23,9 @@
#include "heap-scheduler.h"
#include "event-impl.h"
#include "ns3/assert.h"
#include "ns3/log.h"
#include <string>
#define noTRACE_HEAP 1
#ifdef TRACE_HEAP
#include <iostream>
# define TRACE(x) \
std::cout << "HEAP TRACE " << x << std::endl;
#else /* TRACE_HEAP */
# define TRACE(format,...)
#endif /* TRACE_HEAP */
NS_LOG_COMPONENT_DEFINE ("HeapScheduler");
namespace ns3 {
@@ -103,7 +92,7 @@ void
HeapScheduler::Exch (uint32_t a, uint32_t b)
{
NS_ASSERT (b < m_heap.size () && a < m_heap.size ());
TRACE ("Exch " << a << ", " << b);
NS_LOG_DEBUG ("Exch " << a << ", " << b);
Event tmp (m_heap[a]);
m_heap[a] = m_heap[b];
m_heap[b] = tmp;
@@ -177,49 +166,42 @@ HeapScheduler::TopDown (uint32_t start)
void
HeapScheduler::Insert (const Event &ev)
{
// acquire single ref
ev.impl->Ref ();
m_heap.push_back (ev);
BottomUp ();
}
EventId
Scheduler::Event
HeapScheduler::PeekNext (void) const
{
Event next = m_heap[Root ()];
return EventId (next.impl, next.key.m_ts, next.key.m_uid);
return m_heap[Root ()];
}
EventId
Scheduler::Event
HeapScheduler::RemoveNext (void)
{
Event next = m_heap[Root ()];
Exch (Root (), Last ());
m_heap.pop_back ();
TopDown (Root ());
return EventId (Ptr<EventImpl> (next.impl, false), next.key.m_ts, next.key.m_uid);
return next;
}
bool
HeapScheduler::Remove (const EventId &id)
void
HeapScheduler::Remove (const Event &ev)
{
uint32_t uid = id.GetUid ();
uint32_t uid = ev.key.m_uid;
for (uint32_t i = 1; i < m_heap.size (); i++)
{
if (uid == m_heap[i].key.m_uid)
{
NS_ASSERT (m_heap[i].impl == id.PeekEventImpl ());
// release single ref
m_heap[i].impl->Unref ();
NS_ASSERT (m_heap[i].impl == ev.impl);
Exch (i, Last ());
m_heap.pop_back ();
TopDown (i);
return true;
return;
}
}
NS_ASSERT (false);
// quiet compiler
return false;
}
} // namespace ns3

View File

@@ -27,8 +27,6 @@
namespace ns3 {
class EventHolder;
/**
* \ingroup scheduler
* \brief a binary heap event scheduler
@@ -54,9 +52,9 @@ public:
virtual void Insert (const Event &ev);
virtual bool IsEmpty (void) const;
virtual EventId PeekNext (void) const;
virtual EventId RemoveNext (void);
virtual bool Remove (const EventId &ev);
virtual Event PeekNext (void) const;
virtual Event RemoveNext (void);
virtual void Remove (const Event &ev);
private:
typedef std::vector<Event> BinaryHeap;

View File

@@ -35,8 +35,6 @@ ListScheduler::~ListScheduler ()
void
ListScheduler::Insert (const Event &ev)
{
// acquire refcount on EventImpl
ev.impl->Ref ();
for (EventsI i = m_events.begin (); i != m_events.end (); i++)
{
if (ev.key < i->key)
@@ -52,37 +50,33 @@ ListScheduler::IsEmpty (void) const
{
return m_events.empty ();
}
EventId
Scheduler::Event
ListScheduler::PeekNext (void) const
{
Event next = m_events.front ();
return EventId (next.impl, next.key.m_ts, next.key.m_uid);
return m_events.front ();
}
EventId
Scheduler::Event
ListScheduler::RemoveNext (void)
{
Event next = m_events.front ();
m_events.pop_front ();
return EventId (Ptr<EventImpl> (next.impl,false), next.key.m_ts, next.key.m_uid);
return next;
}
bool
ListScheduler::Remove (const EventId &id)
void
ListScheduler::Remove (const Event &ev)
{
for (EventsI i = m_events.begin (); i != m_events.end (); i++)
{
if (i->key.m_uid == id.GetUid ())
if (i->key.m_uid == ev.key.m_uid)
{
NS_ASSERT (id.PeekEventImpl () == i->impl);
// release single acquire ref.
i->impl->Unref ();
NS_ASSERT (ev.impl == i->impl);
m_events.erase (i);
return true;
return;
}
}
NS_ASSERT (false);
return false;
}
} // namespace ns3

View File

@@ -22,7 +22,6 @@
#define LIST_SCHEDULER_H
#include "scheduler.h"
#include "event-id.h"
#include <list>
#include <utility>
#include <stdint.h>
@@ -35,7 +34,7 @@ class EventImpl;
* \ingroup scheduler
* \brief a std::list event scheduler
*
* This class implements the an event scheduler using an std::list
* This class implements an event scheduler using an std::list
* data structure, that is, a double linked-list.
*/
class ListScheduler : public Scheduler
@@ -46,9 +45,9 @@ class ListScheduler : public Scheduler
virtual void Insert (const Event &ev);
virtual bool IsEmpty (void) const;
virtual EventId PeekNext (void) const;
virtual EventId RemoveNext (void);
virtual bool Remove (const EventId &ev);
virtual Event PeekNext (void) const;
virtual Event RemoveNext (void);
virtual void Remove (const Event &ev);
private:

View File

@@ -22,18 +22,10 @@
#include "map-scheduler.h"
#include "event-impl.h"
#include "ns3/assert.h"
#include "ns3/log.h"
#include <string>
#define noTRACE_MAP 1
#ifdef TRACE_MAP
#include <iostream>
# define TRACE(x) \
std::cout << "MAP TRACE " << x << std::endl;
#else /* TRACE_MAP */
# define TRACE(format,...)
#endif /* TRACE_MAP */
NS_LOG_COMPONENT_DEFINE ("MapScheduler");
namespace ns3 {
@@ -45,8 +37,7 @@ MapScheduler::~MapScheduler ()
void
MapScheduler::Insert (const Event &ev)
{
// acquire a single ref
ev.impl->Ref ();
NS_LOG_FUNCTION (this << ev.impl << ev.key.m_ts << ev.key.m_uid);
std::pair<EventMapI,bool> result;
result = m_list.insert (std::make_pair (ev.key, ev.impl));
NS_ASSERT (result.second);
@@ -58,35 +49,41 @@ MapScheduler::IsEmpty (void) const
return m_list.empty ();
}
EventId
Scheduler::Event
MapScheduler::PeekNext (void) const
{
NS_LOG_FUNCTION (this);
EventMapCI i = m_list.begin ();
NS_ASSERT (i != m_list.end ());
return EventId (i->second, i->first.m_ts, i->first.m_uid);
Event ev;
ev.impl = i->second;
ev.key = i->first;
NS_LOG_DEBUG (this << ev.impl << ev.key.m_ts << ev.key.m_uid);
return ev;
}
EventId
Scheduler::Event
MapScheduler::RemoveNext (void)
{
NS_LOG_FUNCTION (this);
EventMapI i = m_list.begin ();
NS_ASSERT (i != m_list.end ());
std::pair<Scheduler::EventKey, EventImpl*> next = *i;
Event ev;
ev.impl = i->second;
ev.key = i->first;
m_list.erase (i);
return EventId (Ptr<EventImpl> (next.second, false), next.first.m_ts, next.first.m_uid);
NS_LOG_DEBUG (this << ev.impl << ev.key.m_ts << ev.key.m_uid);
return ev;
}
bool
MapScheduler::Remove (const EventId &id)
void
MapScheduler::Remove (const Event &ev)
{
Scheduler::EventKey key;
key.m_ts = id.GetTs ();
key.m_uid = id.GetUid ();
EventMapI i = m_list.find (key);
NS_ASSERT (i->second == id.PeekEventImpl ());
// release single ref.
i->second->Unref ();
NS_LOG_FUNCTION (this << ev.impl << ev.key.m_ts << ev.key.m_uid);
EventMapI i = m_list.find (ev.key);
NS_ASSERT (i->second == ev.impl);
m_list.erase (i);
return true;
}
} // namespace ns3

View File

@@ -28,8 +28,6 @@
namespace ns3 {
class EventImpl;
/**
* \ingroup scheduler
* \brief a std::map event scheduler
@@ -45,9 +43,9 @@ public:
virtual void Insert (const Event &ev);
virtual bool IsEmpty (void) const;
virtual EventId PeekNext (void) const;
virtual EventId RemoveNext (void);
virtual bool Remove (const EventId &ev);
virtual Event PeekNext (void) const;
virtual Event RemoveNext (void);
virtual void Remove (const Event &ev);
private:
typedef std::map<Scheduler::EventKey, EventImpl*> EventMap;

View File

@@ -103,7 +103,8 @@ RealtimeSimulatorImpl::~RealtimeSimulatorImpl ()
NS_LOG_FUNCTION_NOARGS ();
while (m_events->IsEmpty () == false)
{
EventId next = m_events->RemoveNext ();
Scheduler::Event next = m_events->RemoveNext ();
next.impl->Unref ();
}
m_events = 0;
m_synchronizer = 0;
@@ -148,7 +149,7 @@ RealtimeSimulatorImpl::SetScheduler (Ptr<Scheduler> scheduler)
{
while (m_events->IsEmpty () == false)
{
EventId next = m_events->RemoveNext ();
Scheduler::Event next = m_events->RemoveNext ();
scheduler->Insert (next);
}
}
@@ -315,7 +316,7 @@ RealtimeSimulatorImpl::ProcessOneEvent (void)
// is the one we think it is. What we can be sure of is that it is time to execute
// whatever event is at the head of this list if the list is in time order.
//
EventId next;
Scheduler::Event next;
{
CriticalSection cs (m_mutex);
@@ -336,18 +337,18 @@ RealtimeSimulatorImpl::ProcessOneEvent (void)
// for. We can only assume that only that it must be due and cannot cause time
// to move backward.
//
NS_ASSERT_MSG (next.GetTs () >= m_currentTs,
NS_ASSERT_MSG (next.key.m_ts >= m_currentTs,
"RealtimeSimulatorImpl::ProcessOneEvent(): "
"next.GetTs() earlier than m_currentTs (list order error)");
NS_LOG_LOGIC ("handle " << next.GetTs ());
NS_LOG_LOGIC ("handle " << next.key.m_ts);
//
// Update the current simulation time to be the timestamp of the event we're
// executing. From the rest of the simulation's point of view, simulation time
// is frozen until the next event is executed.
//
m_currentTs = next.GetTs ();
m_currentUid = next.GetUid ();
m_currentTs = next.key.m_ts;
m_currentUid = next.key.m_uid;
//
// We're about to run the event and we've done our best to synchronize this
@@ -385,10 +386,11 @@ RealtimeSimulatorImpl::ProcessOneEvent (void)
// event list so we can execute it outside a critical section without fear of someone
// changing things out from under us.
EventImpl *event = next.PeekEventImpl ();
EventImpl *event = next.impl;
m_synchronizer->EventStart ();
event->Invoke ();
m_synchronizer->EventEnd ();
event->Unref ();
}
bool
@@ -413,9 +415,8 @@ RealtimeSimulatorImpl::NextTs (void) const
NS_LOG_FUNCTION_NOARGS ();
NS_ASSERT_MSG (m_events->IsEmpty () == false,
"RealtimeSimulatorImpl::NextTs(): event queue is empty");
EventId id = m_events->PeekNext ();
return id.GetTs ();
Scheduler::Event ev = m_events->PeekNext ();
return ev.key.m_ts;
}
//
@@ -523,7 +524,6 @@ RealtimeSimulatorImpl::RunOneEvent (void)
NS_ASSERT_MSG (m_running == false,
"RealtimeSimulatorImpl::RunOneEvent(): An internal simulator event loop is running");
EventId next;
EventImpl *event = 0;
//
@@ -533,18 +533,18 @@ RealtimeSimulatorImpl::RunOneEvent (void)
{
CriticalSection cs (m_mutex);
next = m_events->RemoveNext ();
Scheduler::Event next = m_events->RemoveNext ();
NS_ASSERT (next.GetTs () >= m_currentTs);
NS_ASSERT (next.key.m_ts >= m_currentTs);
--m_unscheduledEvents;
NS_LOG_LOGIC ("handle " << next.GetTs ());
m_currentTs = next.GetTs ();
m_currentUid = next.GetUid ();
event = next.PeekEventImpl ();
NS_LOG_LOGIC ("handle " << next.key.m_ts);
m_currentTs = next.key.m_ts;
m_currentUid = next.key.m_ts;
event = next.impl;
}
event->Invoke ();
event->Unref ();
}
void
@@ -588,37 +588,12 @@ RealtimeSimulatorImpl::Stop (Time const &time)
//
// Schedule an event for a _relative_ time in the future.
//
// A little side-note on events and multthreading:
//
// This is a little tricky. We get a Ptr<EventImpl> passed down to us in some
// thread context. This Ptr<EventImpl> is not yet shared in any way. It is
// possible however that the calling context is not the context of the main
// scheduler thread (e.g. it is in the context of a separate device thread).
// It would be bad (TM) if we naively wrapped the EventImpl up in an EventId
// that would be accessible from multiple threads without considering thread
// safety.
//
// It's clear that we cannot have a situation where the EventImpl is "owned" by
// multiple threads. The calling thread is free to hold the EventId as long as
// it wants and manage the reference counts to the underlying EventImpl all it
// wants. The scheduler is free to do the same; and will eventually release
// the reference in the context of thread running ProcessOneEvent(). It is
// "a bad thing" (TM) if these two threads decide to release the underlying
// EventImpl "at the same time" since the result is sure to be multiple frees,
// memory leaks or bus errors.
//
// The answer is to make the reference counting of the EventImpl thread safe;
// which we do. We don't want to force the event implementation to carry around
// a mutex, so we "lend" it one using a RealtimeEventLock object (m_eventLock)
// in the constructor of the event and take it back in the destructor. See the
// event code for details.
//
EventId
RealtimeSimulatorImpl::Schedule (Time const &time, const Ptr<EventImpl> &event)
RealtimeSimulatorImpl::Schedule (Time const &time, const Ptr<EventImpl> &impl)
{
NS_LOG_FUNCTION (time << event);
NS_LOG_FUNCTION (time << impl);
EventId id;
Scheduler::Event ev;
{
CriticalSection cs (m_mutex);
//
@@ -630,33 +605,36 @@ RealtimeSimulatorImpl::Schedule (Time const &time, const Ptr<EventImpl> &event)
Time tAbsolute = Simulator::Now () + time;
NS_ASSERT_MSG (tAbsolute.IsPositive (), "RealtimeSimulatorImpl::Schedule(): Negative time");
NS_ASSERT_MSG (tAbsolute >= TimeStep (m_currentTs), "RealtimeSimulatorImpl::Schedule(): time < m_currentTs");
uint64_t ts = (uint64_t) tAbsolute.GetTimeStep ();
id = EventId (event, ts, m_uid);
ev.impl = GetPointer (impl);
ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
ev.key.m_uid = m_uid;
m_uid++;
++m_unscheduledEvents;
m_events->Insert (id);
m_events->Insert (ev);
m_synchronizer->Signal ();
}
return id;
return EventId (impl, ev.key.m_ts, ev.key.m_uid);
}
EventId
RealtimeSimulatorImpl::ScheduleNow (const Ptr<EventImpl> &event)
RealtimeSimulatorImpl::ScheduleNow (const Ptr<EventImpl> &impl)
{
NS_LOG_FUNCTION_NOARGS ();
EventId id;
Scheduler::Event ev;
{
CriticalSection cs (m_mutex);
id = EventId (event, m_currentTs, m_uid);
ev.impl = GetPointer (impl);
ev.key.m_ts = m_currentTs;
ev.key.m_uid = m_uid;
m_uid++;
++m_unscheduledEvents;
m_events->Insert (id);
m_events->Insert (ev);
m_synchronizer->Signal ();
}
return id;
return EventId (impl, ev.key.m_ts, ev.key.m_uid);
}
Time
@@ -669,31 +647,33 @@ RealtimeSimulatorImpl::Now (void) const
// Schedule an event for a _relative_ time in the future.
//
EventId
RealtimeSimulatorImpl::ScheduleRealtime (Time const &time, const Ptr<EventImpl> &event)
RealtimeSimulatorImpl::ScheduleRealtime (Time const &time, const Ptr<EventImpl> &impl)
{
NS_LOG_FUNCTION (time << event);
NS_LOG_FUNCTION (time << impl);
EventId id;
Scheduler::Event ev;
{
CriticalSection cs (m_mutex);
uint64_t ts = m_synchronizer->GetCurrentRealtime () + time.GetTimeStep ();
NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs");
id = EventId (event, ts, m_uid);
ev.impl = GetPointer (impl);
ev.key.m_ts = ts;
ev.key.m_uid = m_uid;
m_uid++;
++m_unscheduledEvents;
m_events->Insert (id);
m_events->Insert (ev);
m_synchronizer->Signal ();
}
return id;
return EventId (impl, ev.key.m_ts, ev.key.m_uid);
}
EventId
RealtimeSimulatorImpl::ScheduleRealtimeNow (const Ptr<EventImpl> &event)
RealtimeSimulatorImpl::ScheduleRealtimeNow (const Ptr<EventImpl> &impl)
{
NS_LOG_FUNCTION_NOARGS ();
EventId id;
Scheduler::Event ev;
{
CriticalSection cs (m_mutex);
@@ -703,14 +683,16 @@ RealtimeSimulatorImpl::ScheduleRealtimeNow (const Ptr<EventImpl> &event)
//
uint64_t ts = m_running ? m_synchronizer->GetCurrentRealtime () : m_currentTs;
NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealrimeNow(): schedule for time < m_currentTs");
id = EventId (event, ts, m_uid);
ev.impl = GetPointer (impl);
ev.key.m_ts = ts;
ev.key.m_uid = m_uid;
m_uid++;
++m_unscheduledEvents;
m_events->Insert (id);
m_events->Insert (ev);
m_synchronizer->Signal ();
}
return id;
return EventId (impl, ev.key.m_ts, ev.key.m_uid);
}
Time
@@ -720,11 +702,11 @@ RealtimeSimulatorImpl::RealtimeNow (void) const
}
EventId
RealtimeSimulatorImpl::ScheduleDestroy (const Ptr<EventImpl> &event)
RealtimeSimulatorImpl::ScheduleDestroy (const Ptr<EventImpl> &impl)
{
NS_LOG_FUNCTION_NOARGS ();
EventId id;
EventId id;
{
CriticalSection cs (m_mutex);
@@ -733,7 +715,7 @@ RealtimeSimulatorImpl::ScheduleDestroy (const Ptr<EventImpl> &event)
// overridden by the uid of 2 which identifies this as an event to be
// executed at Simulator::Destroy time.
//
id = EventId (event, m_currentTs, 2);
id = EventId (impl, m_currentTs, 2);
m_destroyEvents.push_back (id);
m_uid++;
}
@@ -757,16 +739,16 @@ RealtimeSimulatorImpl::GetDelayLeft (const EventId &id) const
}
void
RealtimeSimulatorImpl::Remove (const EventId &ev)
RealtimeSimulatorImpl::Remove (const EventId &id)
{
if (ev.GetUid () == 2)
if (id.GetUid () == 2)
{
// destroy events.
for (DestroyEvents::iterator i = m_destroyEvents.begin ();
i != m_destroyEvents.end ();
i++)
{
if (*i == ev)
if (*i == id)
{
m_destroyEvents.erase (i);
break;
@@ -774,7 +756,7 @@ RealtimeSimulatorImpl::Remove (const EventId &ev)
}
return;
}
if (IsExpired (ev))
if (IsExpired (id))
{
return;
}
@@ -782,11 +764,15 @@ RealtimeSimulatorImpl::Remove (const EventId &ev)
{
CriticalSection cs (m_mutex);
m_events->Remove (ev);
Scheduler::Event event;
event.impl = id.PeekEventImpl ();
event.key.m_ts = id.GetTs ();
event.key.m_uid = id.GetUid ();
m_events->Remove (event);
--m_unscheduledEvents;
Cancel (ev);
event.impl->Cancel ();
event.impl->Unref ();
}
}

View File

@@ -22,11 +22,12 @@
#define SCHEDULER_H
#include <stdint.h>
#include "event-id.h"
#include "ns3/object.h"
namespace ns3 {
class EventImpl;
/**
* \ingroup simulator
* \defgroup scheduler Scheduler
@@ -38,13 +39,16 @@ namespace ns3 {
* This base class specifies the interface used to maintain the
* event list. If you want to provide a new event list scheduler,
* you need to create a subclass of this base class and implement
* all the pure virtual methods defined here. Namely:
* - ns3::Scheduler::Insert
* - ns3::Scheduler::IsEmpty
* - ns3::Scheduler::PeekNext
* - ns3::Scheduler::RemoveNext
* - ns3::Scheduler::Remove
* all the pure virtual methods defined here.
*
* The only tricky aspect of this API is the memory management of
* the EventImpl pointer which is a member of the Event data structure.
* The lifetime of this pointer is assumed to always be longer than
* the lifetime of the Scheduler class which means that the caller
* is responsible for ensuring that this invariant holds through
* calling EventImpl::Ref and EventImpl::Unref at the right time.
* Typically, ::Ref is called before Insert and ::Unref is called
* after a call to one of the Remove methods.
*/
class Scheduler : public Object
{
@@ -76,20 +80,18 @@ class Scheduler : public Object
*
* This method cannot be invoked if the list is empty.
*/
virtual EventId PeekNext (void) const = 0;
virtual Event PeekNext (void) const = 0;
/**
* This method cannot be invoked if the list is empty.
* Remove the next earliest event from the event list.
*/
virtual EventId RemoveNext (void) = 0;
virtual Event RemoveNext (void) = 0;
/**
* \param id the id of the event to remove
* \returns true if the id was found and removed
* successfully, false otherwise.
*
* This methods cannot be invoked if the list is empty.
*/
virtual bool Remove (const EventId &id) = 0;
virtual void Remove (const Event &ev) = 0;
};
/* Note the invariants which this function must provide:

View File

@@ -23,6 +23,7 @@
#include "scheduler.h"
#include "event-impl.h"
#include "event-id.h"
#include "nstime.h"
#include "ns3/ptr.h"