X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4a98c806e5c7c58a8a42ee5b00cef962b79ef50a..9a9e73f6fdc119b856b97962abeb9be38b55683d:/wxPython/src/helpers.cpp diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index 8216a27e4e..340c740037 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -19,6 +19,7 @@ #ifdef __WXMSW__ #include #include +#include #endif #ifdef __WXGTK__ @@ -28,6 +29,36 @@ #endif +//---------------------------------------------------------------------- + +#ifdef __WXGTK__ +int WXDLLEXPORT wxEntryStart( int& argc, char** argv ); +#else +int WXDLLEXPORT wxEntryStart( int argc, char** argv ); +#endif +int WXDLLEXPORT wxEntryInitGui(); +void WXDLLEXPORT wxEntryCleanup(); + +wxPyApp* wxPythonApp = NULL; // Global instance of application object + + +#ifdef WXP_WITH_THREAD +struct wxPyThreadState { + unsigned long tid; + PyThreadState* tstate; + + wxPyThreadState(unsigned long _tid=0, PyThreadState* _tstate=NULL) + : tid(_tid), tstate(_tstate) {} +}; + +#include +WX_DECLARE_OBJARRAY(wxPyThreadState, wxPyThreadStateArray); +#include +WX_DEFINE_OBJARRAY(wxPyThreadStateArray); + +wxPyThreadStateArray* wxPyTStates = NULL; +wxMutex* wxPyTMutex = NULL; +#endif #ifdef __WXMSW__ // If building for win32... @@ -47,11 +78,9 @@ BOOL WINAPI DllMain( #endif //---------------------------------------------------------------------- -// Class for implementing the wxp main application shell. +// Classes for implementing the wxp main application shell. //---------------------------------------------------------------------- -wxPyApp *wxPythonApp = NULL; // Global instance of application object - wxPyApp::wxPyApp() { // printf("**** ctor\n"); @@ -63,43 +92,32 @@ wxPyApp::~wxPyApp() { // This one isn't acutally called... See __wxStart() -bool wxPyApp::OnInit(void) { +bool wxPyApp::OnInit() { return FALSE; } -int wxPyApp::MainLoop(void) { + +int wxPyApp::MainLoop() { int retval = 0; DeletePendingObjects(); + bool initialized = wxTopLevelWindows.GetCount() != 0; #ifdef __WXGTK__ - m_initialized = wxTopLevelWindows.GetCount() != 0; + m_initialized = initialized; #endif - if (Initialized()) { + if (initialized) { retval = wxApp::MainLoop(); - wxPythonApp->OnExit(); + OnExit(); } return retval; } + //--------------------------------------------------------------------- //---------------------------------------------------------------------- -#ifdef __WXMSW__ -#include "wx/msw/msvcrt.h" -#endif - - -int WXDLLEXPORT wxEntryStart( int argc, char** argv ); -int WXDLLEXPORT wxEntryInitGui(); -void WXDLLEXPORT wxEntryCleanup(); - - -#ifdef WXP_WITH_THREAD -PyInterpreterState* wxPyInterpreter = NULL; -#endif - // This is where we pick up the first part of the wxEntry functionality... // The rest is in __wxStart and __wxCleanup. This function is called when @@ -113,7 +131,8 @@ void __wxPreStart() #ifdef WXP_WITH_THREAD PyEval_InitThreads(); - wxPyInterpreter = PyThreadState_Get()->interp; + wxPyTStates = new wxPyThreadStateArray; + wxPyTMutex = new wxMutex; #endif // Bail out if there is already windows created. This means that the @@ -201,8 +220,16 @@ PyObject* __wxStart(PyObject* /* self */, PyObject* args) return Py_None; } + void __wxCleanup() { wxEntryCleanup(); +#ifdef WXP_WITH_THREAD + delete wxPyTMutex; + wxPyTMutex = NULL; + wxPyTStates->Empty(); + delete wxPyTStates; + wxPyTStates = NULL; +#endif } @@ -229,8 +256,8 @@ PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args) #ifdef __WXMOTIF__ #define wxPlatform "__WXMOTIF__" #endif -#ifdef __WXQT__ -#define wxPlatform "__WXQT__" +#ifdef __WXX11__ +#define wxPlatform "__WXX11__" #endif #ifdef __WXGTK__ #define wxPlatform "__WXGTK__" @@ -261,7 +288,6 @@ PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args) void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) { if (! wxPyPtrTypeMap) wxPyPtrTypeMap = PyDict_New(); - PyDict_SetItemString(wxPyPtrTypeMap, (char*)commonName, PyString_FromString((char*)ptrName)); @@ -400,7 +426,7 @@ PyObject* wxPyConstructObject(void* ptr, char buff[64]; // should always be big enough... sprintf(buff, "%sPtr", className); - wxASSERT_MSG(wxPython_dict, "wxPython_dict is not set yet!!"); + wxASSERT_MSG(wxPython_dict, "wxPython_dict is not set yet!!"); PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff); if (! classobj) { @@ -418,29 +444,94 @@ PyObject* wxPyConstructObject(void* ptr, //--------------------------------------------------------------------------- -wxPyTState* wxPyBeginBlockThreads() { - wxPyTState* state = NULL; #ifdef WXP_WITH_THREAD - if (1) { // Can I check if I've already got the lock? - state = new wxPyTState; - PyEval_AcquireLock(); - state->newState = PyThreadState_New(wxPyInterpreter); - state->prevState = PyThreadState_Swap(state->newState); +inline +unsigned long wxPyGetCurrentThreadId() { + return wxThread::GetCurrentId(); +} + +static PyThreadState* gs_shutdownTState; +static +PyThreadState* wxPyGetThreadState() { + if (wxPyTMutex == NULL) // Python is shutting down... + return gs_shutdownTState; + + unsigned long ctid = wxPyGetCurrentThreadId(); + PyThreadState* tstate = NULL; + + wxPyTMutex->Lock(); + for(size_t i=0; i < wxPyTStates->GetCount(); i++) { + wxPyThreadState& info = wxPyTStates->Item(i); + if (info.tid == ctid) { + tstate = info.tstate; + break; + } + } + wxPyTMutex->Unlock(); + wxASSERT_MSG(tstate, "PyThreadState should not be NULL!"); + return tstate; +} + +static +void wxPySaveThreadState(PyThreadState* tstate) { + if (wxPyTMutex == NULL) { // Python is shutting down, assume a single thread... + gs_shutdownTState = tstate; + return; + } + unsigned long ctid = wxPyGetCurrentThreadId(); + wxPyTMutex->Lock(); + for(size_t i=0; i < wxPyTStates->GetCount(); i++) { + wxPyThreadState& info = wxPyTStates->Item(i); + if (info.tid == ctid) { + info.tstate = tstate; + wxPyTMutex->Unlock(); + return; + } } + // not found, so add it... + wxPyTStates->Add(new wxPyThreadState(ctid, tstate)); + wxPyTMutex->Unlock(); +} + +#endif + + +// Calls from Python to wxWindows code are wrapped in calls to these +// functions: + +PyThreadState* wxPyBeginAllowThreads() { +#ifdef WXP_WITH_THREAD + PyThreadState* saved = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS; + wxPySaveThreadState(saved); + return saved; +#else + return NULL; #endif - return state; } +void wxPyEndAllowThreads(PyThreadState* saved) { +#ifdef WXP_WITH_THREAD + PyEval_RestoreThread(saved); // Py_END_ALLOW_THREADS; +#endif +} + + -void wxPyEndBlockThreads(wxPyTState* state) { +// Calls from wxWindows back to Python code, or even any PyObject +// manipulations, PyDECREF's and etc. are wrapped in calls to these functions: + +void wxPyBeginBlockThreads() { #ifdef WXP_WITH_THREAD - if (state) { - PyThreadState_Swap(state->prevState); - PyThreadState_Clear(state->newState); - PyEval_ReleaseLock(); - PyThreadState_Delete(state->newState); - delete state; - } + PyThreadState* tstate = wxPyGetThreadState(); + PyEval_RestoreThread(tstate); +#endif +} + + +void wxPyEndBlockThreads() { +#ifdef WXP_WITH_THREAD + PyThreadState* tstate = PyEval_SaveThread(); + // Is there any need to save it again? #endif } @@ -460,9 +551,9 @@ wxPyCallback::wxPyCallback(const wxPyCallback& other) { } wxPyCallback::~wxPyCallback() { - wxPyTState* state = wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); Py_DECREF(m_func); - wxPyEndBlockThreads(state); + wxPyEndBlockThreads(); } @@ -476,7 +567,7 @@ void wxPyCallback::EventThunker(wxEvent& event) { PyObject* tuple; - wxPyTState* state = wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); wxString className = event.GetClassInfo()->GetClassName(); if (className == "wxPyEvent") @@ -496,7 +587,7 @@ void wxPyCallback::EventThunker(wxEvent& event) { } else { PyErr_Print(); } - wxPyEndBlockThreads(state); + wxPyEndBlockThreads(); } @@ -681,10 +772,10 @@ PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTu void wxPyCBH_delete(wxPyCallbackHelper* cbh) { if (cbh->m_incRef) { - wxPyTState* state = wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); Py_XDECREF(cbh->m_self); Py_XDECREF(cbh->m_class); - wxPyEndBlockThreads(state); + wxPyEndBlockThreads(); } } @@ -702,14 +793,14 @@ wxPyEvtSelfRef::wxPyEvtSelfRef() { } wxPyEvtSelfRef::~wxPyEvtSelfRef() { - wxPyTState* state = wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); if (m_cloned) Py_DECREF(m_self); - wxPyEndBlockThreads(state); + wxPyEndBlockThreads(); } void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) { - wxPyTState* state = wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); if (m_cloned) Py_DECREF(m_self); m_self = self; @@ -717,7 +808,7 @@ void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) { Py_INCREF(m_self); m_cloned = TRUE; } - wxPyEndBlockThreads(state); + wxPyEndBlockThreads(); } PyObject* wxPyEvtSelfRef::GetSelf() const { @@ -774,9 +865,9 @@ wxPyTimer::wxPyTimer(PyObject* callback) { } wxPyTimer::~wxPyTimer() { - wxPyTState* state = wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); Py_DECREF(func); - wxPyEndBlockThreads(state); + wxPyEndBlockThreads(); } void wxPyTimer::Notify() { @@ -784,7 +875,7 @@ void wxPyTimer::Notify() { wxTimer::Notify(); } else { - wxPyTState* state = wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); PyObject* result; PyObject* args = Py_BuildValue("()"); @@ -798,7 +889,7 @@ void wxPyTimer::Notify() { PyErr_Print(); } - wxPyEndBlockThreads(state); + wxPyEndBlockThreads(); } } @@ -814,7 +905,7 @@ PyObject* wxPy_ConvertList(wxListBase* list, const char* className) { wxObject* wxObj; wxNode* node = list->First(); - wxPyTState* state = wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); pyList = PyList_New(0); while (node) { wxObj = node->Data(); @@ -822,7 +913,7 @@ PyObject* wxPy_ConvertList(wxListBase* list, const char* className) { PyList_Append(pyList, pyObj); node = node->Next(); } - wxPyEndBlockThreads(state); + wxPyEndBlockThreads(); return pyList; } @@ -1408,6 +1499,18 @@ PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) { } +PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) { + + PyObject* list = PyList_New(0); + for (size_t i=0; i < arr.GetCount(); i++) { + PyObject* number = PyInt_FromLong(arr[i]); + PyList_Append(list, number); + Py_DECREF(number); + } + return list; +} + + //---------------------------------------------------------------------- //----------------------------------------------------------------------