diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sim/eventq.cc | 5 | ||||
-rw-r--r-- | src/sim/eventq.hh | 55 | ||||
-rw-r--r-- | src/sim/eventq_impl.hh | 9 |
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); |