#define __SYSTEMC_CORE_SCHED_EVENT_HH__
#include <functional>
+#include <list>
#include "base/types.hh"
namespace sc_gem5
{
+class ScEvent;
+
+typedef std::list<ScEvent *> ScEvents;
+
class ScEvent
{
private:
std::function<void()> work;
Tick _when;
- bool _scheduled;
+ ScEvents *_events;
+ ScEvents::iterator _it;
friend class Scheduler;
void
- schedule(Tick w)
+ schedule(ScEvents &events, Tick w)
{
when(w);
- _scheduled = true;
+ assert(!scheduled());
+ _events = &events;
+ _events->push_back(this);
+ _it = _events->end();
+ _it--;
}
- void deschedule() { _scheduled = false; }
+ void
+ deschedule()
+ {
+ assert(scheduled());
+ _events->erase(_it);
+ _events = nullptr;
+ }
public:
ScEvent(std::function<void()> work) :
- work(work), _when(MaxTick), _scheduled(false)
+ work(work), _when(MaxTick), _events(nullptr)
{}
~ScEvent();
- bool scheduled() { return _scheduled; }
+ bool scheduled() { return _events != nullptr; }
+ ScEvents *scheduledOn() { return _events; }
void when(Tick w) { _when = w; }
Tick when() { return _when; }
Scheduler::clear()
{
// Delta notifications.
- for (auto &e: deltas)
- e->deschedule();
- deltas.clear();
+ while (!deltas.empty())
+ deltas.front()->deschedule();
// Timed notifications.
for (auto &tsp: timeSlots) {
TimeSlot *&ts = tsp.second;
- for (auto &e: ts->events)
- e->deschedule();
+ while (!ts->events.empty())
+ ts->events.front()->deschedule();
deschedule(ts);
}
timeSlots.clear();
update();
- for (auto &e: deltas)
- e->run();
- deltas.clear();
+ while (!deltas.empty())
+ deltas.front()->run();
for (auto ets: eventsToSchedule)
eq->schedule(ets.first, ets.second);
update();
// The delta phase.
- for (auto &e: deltas)
- e->run();
- deltas.clear();
+ while (!deltas.empty())
+ deltas.front()->run();
if (!runToTime && starved())
scheduleStarvationEvent();
class Scheduler
{
public:
- typedef std::set<ScEvent *> ScEvents;
+ typedef std::list<ScEvent *> ScEvents;
class TimeSlot : public ::Event
{
if (tick < getCurTick())
tick = getCurTick();
- event->schedule(tick);
-
// Delta notification/timeout.
if (delay.value() == 0) {
- deltas.insert(event);
+ event->schedule(deltas, tick);
scheduleReadyEvent();
return;
}
ts = new TimeSlot;
schedule(ts, tick);
}
- ts->events.insert(event);
+ event->schedule(ts->events, tick);
}
// For descheduling delayed/timed notifications/timeouts.
void
deschedule(ScEvent *event)
{
- if (event->when() == getCurTick()) {
- // Attempt to remove from delta notifications.
- if (deltas.erase(event) == 1) {
- event->deschedule();
- return;
- }
+ ScEvents *on = event->scheduledOn();
+
+ if (on == &deltas) {
+ event->deschedule();
+ return;
}
// Timed notification/timeout.
"Descheduling event at time with no events.");
TimeSlot *ts = tsit->second;
ScEvents &events = ts->events;
- assert(events.erase(event));
+ assert(on == &events);
event->deschedule();
// If no more events are happening at this time slot, get rid of it.
inline void
Scheduler::TimeSlot::process()
{
- for (auto &e: events)
- e->run();
+ while (!events.empty())
+ events.front()->run();
scheduler.completeTimeSlot(this);
}