python: Fix the reference counting for python events placed on the eventq.
We need to add a reference when an object is put on the C++ queue, and remove a reference when the object is removed from the queue. This was not happening before and caused a memory problem.
This commit is contained in:
parent
1adfe5c7f3
commit
4e02e7c217
5 changed files with 40 additions and 23 deletions
|
@ -36,7 +36,7 @@ mainq = internal.event.cvar.mainEventQueue
|
||||||
def create(obj, priority=None):
|
def create(obj, priority=None):
|
||||||
if priority is None:
|
if priority is None:
|
||||||
priority = internal.event.Event.Default_Pri
|
priority = internal.event.Event.Default_Pri
|
||||||
return internal.event.PythonEvent(obj, priority)
|
return PythonEvent(obj, priority)
|
||||||
|
|
||||||
class Event(PythonEvent):
|
class Event(PythonEvent):
|
||||||
def __init__(self, priority=None):
|
def __init__(self, priority=None):
|
||||||
|
|
|
@ -41,6 +41,35 @@
|
||||||
|
|
||||||
#pragma SWIG nowarn=350,351
|
#pragma SWIG nowarn=350,351
|
||||||
|
|
||||||
|
%extend EventQueue {
|
||||||
|
void
|
||||||
|
schedule(Event *event, Tick when)
|
||||||
|
{
|
||||||
|
// Any python event that are scheduled must have their
|
||||||
|
// internal object's refcount incremented so that the object
|
||||||
|
// sticks around while it is in the event queue.
|
||||||
|
PythonEvent *pyevent = dynamic_cast<PythonEvent *>(event);
|
||||||
|
if (pyevent)
|
||||||
|
pyevent->incref();
|
||||||
|
$self->schedule(event, when);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
deschedule(Event *event)
|
||||||
|
{
|
||||||
|
$self->deschedule(event);
|
||||||
|
|
||||||
|
// Now that we're removing the python object from the event
|
||||||
|
// queue, we need to decrement its reference count.
|
||||||
|
PythonEvent *pyevent = dynamic_cast<PythonEvent *>(event);
|
||||||
|
if (pyevent)
|
||||||
|
pyevent->decref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%ignore EventQueue::schedule;
|
||||||
|
%ignore EventQueue::deschedule;
|
||||||
|
|
||||||
%import "base/fast_alloc.hh"
|
%import "base/fast_alloc.hh"
|
||||||
%import "sim/serialize.hh"
|
%import "sim/serialize.hh"
|
||||||
|
|
||||||
|
|
|
@ -38,15 +38,10 @@ PythonEvent::PythonEvent(PyObject *obj, Priority priority)
|
||||||
{
|
{
|
||||||
if (object == NULL)
|
if (object == NULL)
|
||||||
panic("Passed in invalid object");
|
panic("Passed in invalid object");
|
||||||
|
|
||||||
Py_INCREF(object);
|
|
||||||
|
|
||||||
setFlags(AutoDelete);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PythonEvent::~PythonEvent()
|
PythonEvent::~PythonEvent()
|
||||||
{
|
{
|
||||||
Py_DECREF(object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -65,6 +60,10 @@ PythonEvent::process()
|
||||||
async_event = true;
|
async_event = true;
|
||||||
async_exception = true;
|
async_exception = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since the object has been removed from the event queue, its
|
||||||
|
// reference count must be decremented.
|
||||||
|
Py_DECREF(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
CountedDrainEvent *
|
CountedDrainEvent *
|
||||||
|
@ -85,17 +84,3 @@ cleanupCountedDrain(Event *counted_drain)
|
||||||
assert(event->getCount() == 0);
|
assert(event->getCount() == 0);
|
||||||
delete event;
|
delete event;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
Event *
|
|
||||||
create(PyObject *object, Event::Priority priority)
|
|
||||||
{
|
|
||||||
return new PythonEvent(object, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
destroy(Event *event)
|
|
||||||
{
|
|
||||||
delete event;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -43,6 +43,9 @@ class PythonEvent : public Event
|
||||||
PythonEvent(PyObject *obj, Event::Priority priority);
|
PythonEvent(PyObject *obj, Event::Priority priority);
|
||||||
~PythonEvent();
|
~PythonEvent();
|
||||||
|
|
||||||
|
void incref() { Py_INCREF(object); }
|
||||||
|
void decref() { Py_DECREF(object); }
|
||||||
|
|
||||||
virtual void process();
|
virtual void process();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -299,9 +299,9 @@ class EventQueue : public Serializable
|
||||||
virtual const std::string name() const { return objName; }
|
virtual const std::string name() const { return objName; }
|
||||||
|
|
||||||
// schedule the given event on this queue
|
// schedule the given event on this queue
|
||||||
void schedule(Event *ev, Tick when);
|
void schedule(Event *event, Tick when);
|
||||||
void deschedule(Event *ev);
|
void deschedule(Event *event);
|
||||||
void reschedule(Event *ev, Tick when, bool always = false);
|
void reschedule(Event *event, Tick when, bool always = false);
|
||||||
|
|
||||||
Tick nextTick() const { return head->when(); }
|
Tick nextTick() const { return head->when(); }
|
||||||
Event *serviceOne();
|
Event *serviceOne();
|
||||||
|
|
Loading…
Reference in a new issue