//---------------------------------------------------------------------------
-//static bool _wxPyInEvent = false;
-//static unsigned int _wxPyNestCount = 0;
+static unsigned int _wxPyNestCount = 0;
-HELPEREXPORT bool wxPyRestoreThread() {
-// #ifdef WXP_WITH_THREAD
-// //if (wxPyEventThreadState != PyThreadState_Get()) {
-// if (! _wxPyInEvent) {
-// PyEval_RestoreThread(wxPyEventThreadState);
-// _wxPyInEvent = true;
-// return TRUE;
-// } else
-// #endif
-// return FALSE;
+static PyThreadState* myPyThreadState_Get() {
+ PyThreadState* current;
+ current = PyThreadState_Swap(NULL);
+ PyThreadState_Swap(current);
+ return current;
+}
+
+HELPEREXPORT bool wxPyRestoreThread() {
// NOTE: The Python API docs state that if a thread already has the
// interpreter lock and calls PyEval_RestoreThread again a deadlock
- // occurs, so I put in the above code as a guard condition since there are
- // many possibilites for nested events and callbacks in wxPython.
+ // occurs, so I put in this code as a guard condition since there are
+ // many possibilites for nested events and callbacks in wxPython. If
+ // The current thread is our thread, then we can assume that we
+ // already have the lock.
//
- // Unfortunately, it seems like somebody was lying (or I'm not
- // understanding...) because each of the nested calls to this function
- // MUST call PyEval_RestoreThread or Python pukes with a thread error (at
- // least on Win32.)
- //
- // until I know better, this is how I am doing it instead:
#ifdef WXP_WITH_THREAD
- PyEval_RestoreThread(wxPyEventThreadState);
-// _wxPyNestCount += 1;
-// if (_wxPyNestCount == 1)
-// return TRUE;
-// else
+ _wxPyNestCount += 1;
+ if (wxPyEventThreadState != myPyThreadState_Get()) {
+ PyEval_RestoreThread(wxPyEventThreadState);
+ return TRUE;
+ }
+ else
#endif
return FALSE;
}
HELPEREXPORT void wxPySaveThread(bool doSave) {
#ifdef WXP_WITH_THREAD
-// if (doSave) {
+ if (doSave) {
wxPyEventThreadState = PyEval_SaveThread();
-// _wxPyInEvent = false;
-// }
-// _wxPyNestCount -= 1;
+ }
+ _wxPyNestCount -= 1;
#endif
}
-
// This function is used for all events destined for Python event handlers.
void wxPyCallback::EventThunker(wxEvent& event) {
wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
#define IMP_PYCALLBACK_BOOL_DC4DBLBOOL(CLASS, PCLASS, CBNAME) \
bool CLASS::CBNAME(wxDC& a, double b, double c, double d, double e, bool f) { \
bool doSave = wxPyRestoreThread(); \
+ bool rval; \
if (m_myInst.findCallback(#CBNAME)) \
- return m_myInst.callCallback(Py_BuildValue("(Oddddi)", \
+ rval = m_myInst.callCallback(Py_BuildValue("(Oddddi)", \
wxPyConstructObject(&a, "wxDC"), \
b, c, d, e, (int)f)); \
else \
- return PCLASS::CBNAME(a, b, c, d, e, f); \
+ rval = PCLASS::CBNAME(a, b, c, d, e, f); \
wxPySaveThread(doSave); \
+ return rval; \
} \
bool CLASS::base_##CBNAME(wxDC& a, double b, double c, double d, double e, bool f) {\
return PCLASS::CBNAME(a, b, c, d, e, f); \