Allow the OOR reference to be saved without doing an INCREF. This

solves the circular reference problem with wx.Timer.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31095 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2004-12-20 22:50:29 +00:00
parent 56a52e9094
commit 94fd5e4dc1
6 changed files with 65 additions and 28 deletions

View File

@@ -73,9 +73,9 @@ public:
}
%extend {
void _setOORInfo(PyObject* _self) {
void _setOORInfo(PyObject* _self, bool incref=true) {
if (_self && _self != Py_None) {
self->SetClientObject(new wxPyOORClientData(_self));
self->SetClientObject(new wxPyOORClientData(_self, incref));
}
else {
wxPyOORClientData* data = (wxPyOORClientData*)self->GetClientObject();

View File

@@ -35,7 +35,14 @@ enum {
//IMP_PYCALLBACK__(wxPyTimer, wxTimer, Notify);
IMPLEMENT_ABSTRACT_CLASS(wxPyTimer, wxTimer);
wxPyTimer::wxPyTimer(wxEvtHandler *owner, int id)
: wxTimer(owner, id)
{
if (owner == NULL) SetOwner(this);
}
void wxPyTimer::Notify() {
bool found;
bool blocked = wxPyBeginBlockThreads();
@@ -58,7 +65,11 @@ MustHaveApp(wxPyTimer);
%name(Timer) class wxPyTimer : public wxEvtHandler
{
public:
%pythonAppend wxPyTimer "self._setCallbackInfo(self, Timer, 0); self._setOORInfo(self)"
// Don't let the OOR or callback info hold references to the object so
// there won't be a reference cycle and it can clean itself up via normal
// Python refcounting
%pythonAppend wxPyTimer
"self._setCallbackInfo(self, Timer, 0); self._setOORInfo(self, 0)"
// if you don't call SetOwner() or provide an owner in the contstructor
@@ -66,6 +77,8 @@ public:
// notification. If the owner is set then it will get the timer
// notifications which can be handled with EVT_TIMER.
wxPyTimer(wxEvtHandler *owner=NULL, int id = -1);
// Destructor.
virtual ~wxPyTimer();
void _setCallbackInfo(PyObject* self, PyObject* _class, int incref=1);
@@ -101,6 +114,11 @@ public:
// return the timer ID
int GetId() const;
%pythoncode {
def Destroy():
"""NO-OP: Timers must be destroyed by normal refrence counting"""
pass
}
};

View File

@@ -866,17 +866,6 @@ bool wxPyCheckForApp() {
//---------------------------------------------------------------------------
void wxPyClientData_dtor(wxPyClientData* self) {
if (! wxPyDoingCleanup) { // Don't do it during cleanup as Python
// may have already garbage collected the object...
bool blocked = wxPyBeginBlockThreads();
Py_DECREF(self->m_obj);
self->m_obj = NULL;
wxPyEndBlockThreads(blocked);
}
}
void wxPyUserData_dtor(wxPyUserData* self) {
if (! wxPyDoingCleanup) {
bool blocked = wxPyBeginBlockThreads();
@@ -887,6 +876,20 @@ void wxPyUserData_dtor(wxPyUserData* self) {
}
void wxPyClientData_dtor(wxPyClientData* self) {
if (! wxPyDoingCleanup) { // Don't do it during cleanup as Python
// may have already garbage collected the object...
if (self->m_incRef) {
bool blocked = wxPyBeginBlockThreads();
Py_DECREF(self->m_obj);
wxPyEndBlockThreads(blocked);
}
self->m_obj = NULL;
}
}
// This is called when an OOR controled object is being destroyed. Although
// the C++ object is going away there is no way to force the Python object
// (and all references to it) to die too. This causes problems (crashes) in
@@ -909,8 +912,9 @@ void wxPyOORClientData_dtor(wxPyOORClientData* self) {
}
// Only if there is more than one reference to the object
if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 ) {
// Only if there is more than one reference to the object and we are
// holding the OOR reference:
if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 && self->m_incRef) {
// bool isInstance = wxPyInstance_Check(self->m_obj);
// TODO same here
//wxASSERT_MSG(isInstance, wxT("m_obj not an instance!?!?!"));