summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/sim/eventq.cc5
-rw-r--r--src/sim/eventq.hh55
-rw-r--r--src/sim/eventq_impl.hh9
3 files changed, 61 insertions, 8 deletions
diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc
index 7c2648c64..3e27bcf1c 100644
--- a/src/sim/eventq.cc
+++ b/src/sim/eventq.cc
@@ -227,7 +227,7 @@ EventQueue::serviceOne()
event->process();
if (event->isExitEvent()) {
- assert(!event->flags.isSet(Event::AutoDelete) ||
+ assert(!event->flags.isSet(Event::Managed) ||
!event->flags.isSet(Event::IsMainQueue)); // would be silly
return event;
}
@@ -235,8 +235,7 @@ EventQueue::serviceOne()
event->flags.clear(Event::Squashed);
}
- if (event->flags.isSet(Event::AutoDelete) && !event->scheduled())
- delete event;
+ event->release();
return NULL;
}
diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh
index 95a36ca7b..b138f56b0 100644
--- a/src/sim/eventq.hh
+++ b/src/sim/eventq.hh
@@ -99,7 +99,8 @@ class EventBase
static const FlagsType PublicWrite = 0x001d; // public writable flags
static const FlagsType Squashed = 0x0001; // has been squashed
static const FlagsType Scheduled = 0x0002; // has been scheduled
- static const FlagsType AutoDelete = 0x0004; // delete after dispatch
+ static const FlagsType Managed = 0x0004; // Use life cycle manager
+ static const FlagsType AutoDelete = Managed; // delete after dispatch
/**
* This used to be AutoSerialize. This value can't be reused
* without changing the checkpoint version since the flag field
@@ -282,6 +283,55 @@ class Event : public EventBase, public Serializable
// This function isn't really useful if TRACING_ON is not defined
virtual void trace(const char *action); //!< trace event activity
+ protected: /* Memory management */
+ /**
+ * @{
+ * Memory management hooks for events that have the Managed flag set
+ *
+ * Events can use automatic memory management by setting the
+ * Managed flag. The default implementation automatically deletes
+ * events once they have been removed from the event queue. This
+ * typically happens when events are descheduled or have been
+ * triggered and not rescheduled.
+ *
+ * The methods below may be overridden by events that need custom
+ * memory management. For example, events exported to Python need
+ * to impement reference counting to ensure that the Python
+ * implementation of the event is kept alive while it lives in the
+ * event queue.
+ *
+ * @note Memory managers are responsible for implementing
+ * reference counting (by overriding both acquireImpl() and
+ * releaseImpl()) or checking if an event is no longer scheduled
+ * in releaseImpl() before deallocating it.
+ */
+
+ /**
+ * Managed event scheduled and being held in the event queue.
+ */
+ void acquire()
+ {
+ if (flags.isSet(Event::Managed))
+ acquireImpl();
+ }
+
+ /**
+ * Managed event removed from the event queue.
+ */
+ void release() {
+ if (flags.isSet(Event::Managed))
+ releaseImpl();
+ }
+
+ virtual void acquireImpl() {}
+
+ virtual void releaseImpl() {
+ if (!scheduled())
+ delete this;
+ }
+
+ /** @} */
+
public:
/*
@@ -340,7 +390,8 @@ class Event : public EventBase, public Serializable
bool isExitEvent() const { return flags.isSet(IsExitEvent); }
/// Check whether this event will auto-delete
- bool isAutoDelete() const { return flags.isSet(AutoDelete); }
+ bool isManaged() const { return flags.isSet(Managed); }
+ bool isAutoDelete() const { return isManaged(); }
/// Get the time that the event is scheduled
Tick when() const { return _when; }
diff --git a/src/sim/eventq_impl.hh b/src/sim/eventq_impl.hh
index 360731d7b..f0755ac8f 100644
--- a/src/sim/eventq_impl.hh
+++ b/src/sim/eventq_impl.hh
@@ -59,6 +59,7 @@ EventQueue::schedule(Event *event, Tick when, bool global)
insert(event);
}
event->flags.set(Event::Scheduled);
+ event->acquire();
if (DTRACE(Event))
event->trace("scheduled");
@@ -79,8 +80,7 @@ EventQueue::deschedule(Event *event)
if (DTRACE(Event))
event->trace("descheduled");
- if (event->flags.isSet(Event::AutoDelete))
- delete event;
+ event->release();
}
inline void
@@ -91,8 +91,11 @@ EventQueue::reschedule(Event *event, Tick when, bool always)
assert(event->initialized());
assert(!inParallelMode || this == curEventQueue());
- if (event->scheduled())
+ if (event->scheduled()) {
remove(event);
+ } else {
+ event->acquire();
+ }
event->setWhen(when, this);
insert(event);