Skip to content

Instantly share code, notes, and snippets.

@kevinw
Created January 13, 2011 18:24
Show Gist options
  • Save kevinw/778340 to your computer and use it in GitHub Desktop.
Save kevinw/778340 to your computer and use it in GitHub Desktop.
extern "C" {static void release_wxTimer(void *, int);}
static void release_wxTimer(void *sipCppV,int state)
{
if (!wxIsMainThread()) {
wxpy_add_pending_delete(&sipType__wxcore_wxTimer, sipCppV, state);
} else {
wxpy_remove_pending_delete(&sipType__wxcore_wxTimer, sipCppV, state);
if (state & SIP_DERIVED_CLASS)
delete reinterpret_cast<sipwxTimer *>(sipCppV);
else
delete reinterpret_cast<wxTimer *>(sipCppV);
}
}
/**
* wxObject subclasses do reference counting with copy on write semantics.
* Unfortunately, the reference counting is not threadsafe.
*
* Since these bindings allow some wxObject subclasses to be owned by Python,
* and destroyed by Python when their Python objects' reference count hits
* zero, we need to watch out for the case when a cycle is broken by the
* garbage collector on a thread other than the main thread.
*
* Normally this would result in the wxObject destructor running on a
* subthread--which we don't want. So we make the generated code call this
* method instead, which adds the object (via PyCObject_FromVoidPtr) to the set
* at app->pendingDelete. Then periodically we call wxpy_flush_pending_delete
* to empty the set and delete its members.
*/
static void wxpy_do_pending_delete(int add, sipClassTypeDef *type, void *sipCppV, int state)
{
wxPyApp* app = (wxPyApp*)wxTheApp;
PyObject* type_vp = PyCObject_FromVoidPtr(type, NULL);
PyObject* cpp_vp = PyCObject_FromVoidPtr(sipCppV, NULL);
PyObject* to_delete = Py_BuildValue("OOi", type_vp, cpp_vp, state);
if (to_delete) {
if (add)
PySet_Add(app->pendingDelete, to_delete);
else
PySet_Discard(app->pendingDelete, to_delete);
Py_DECREF(to_delete);
}
Py_DECREF(type_vp);
Py_DECREF(cpp_vp);
}
void wxpy_add_pending_delete(sipClassTypeDef *type, void *sipCppV, int state)
{
wxpy_do_pending_delete(1, type, sipCppV, state);
}
void wxpy_remove_pending_delete(sipClassTypeDef *type, void *sipCppV, int state)
{
wxpy_do_pending_delete(0, type, sipCppV, state);
}
// call destructors on all objects pending deletion and clear the list
static int wxpy_flush_pending_delete()
{
int count = 0;
SIP_BLOCK_THREADS
PyObject* pendingDelete = ((wxPyApp*)wxTheApp)->pendingDelete;
while (PySet_GET_SIZE(pendingDelete)) {
// TODO: elements are popped off the set in an arbitrary order. is this ok?
PyObject* to_delete = PySet_Pop(pendingDelete);
if (!to_delete)
return count;
// parse (sipTypeDef*, sipWrapper*, and int) out of the tuple
PyObject* type_cobj = PyTuple_GET_ITEM(to_delete, 0);
PyObject* cpp_cobj = PyTuple_GET_ITEM(to_delete, 1);
int state = PyInt_AsLong(PyTuple_GET_ITEM(to_delete, 2));
// convert PyCObject void pointer objects to actual void*s
sipClassTypeDef* type = (sipClassTypeDef*)PyCObject_AsVoidPtr(type_cobj);
void* sipCppV = PyCObject_AsVoidPtr(cpp_cobj);
// invoke the destructor
type->ctd_release(sipCppV, state);
++count;
Py_DECREF(to_delete);
}
SIP_UNBLOCK_THREADS
return count;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment