Created
January 13, 2011 18:24
-
-
Save kevinw/778340 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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