diff --git a/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/FrameworkManagerProxy.h b/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/FrameworkManagerProxy.h index 32ee98c3dd5a944f436bc82b79fa539eb5f0bfa6..9d350b1af3d4733f4f9757cb1d75fdfb9609b04e 100644 --- a/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/FrameworkManagerProxy.h +++ b/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/FrameworkManagerProxy.h @@ -141,15 +141,6 @@ public: virtual void workspaceStoreCleared() {} //@} - /** Set GIL state - * @param lock :: If true, the next call to Python will acquire the GIL before the call. Note that it is unlocked automatically - */ - static void setGILRequired(bool lock) { g_gil_required = lock; } - /** Return if we need to aquire the GIL - * @returns A flag indicating if the thread lock is necessary - */ - static bool requireGIL() { return g_gil_required; } - ///Send a log message to the Mantid Framework with a specified priority void sendLogMessage(const std::string & msg); /// Create the simple Python API for Mantid @@ -161,13 +152,6 @@ public: void releaseFreeMemory(); - protected: - /** A flag indicating whether code has been executed from within Python. This is a bit of a hack - * so that the notification signals don't cause deadlocks if they happen to get called from - * a thread that did not originate from within Python - */ - static bool g_gil_required; - private: /// Copy constructor FrameworkManagerProxy(const FrameworkManagerProxy&); diff --git a/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/PyAlgorithmWrapper.h b/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/PyAlgorithmWrapper.h index 0d6d5bb476f232d4d2c34b3b2825f8d8819f6dda..30f6dd58e2e43f8acabf4ee3db4f9d1efc7d8825 100644 --- a/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/PyAlgorithmWrapper.h +++ b/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/PyAlgorithmWrapper.h @@ -276,11 +276,7 @@ public: /// Called when a delete is performed inside a shared pointer virtual void kill() { - PythonLocker gil; - if( FrameworkManagerProxy::requireGIL() ) - { - gil.lock(); - } + PythonGIL gil; // !----- // This order is very important as the decref causes Python to call the destructor on this object // and the destructor checks the value of the killed flag diff --git a/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/PythonInterfaceFunctions.h b/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/PythonInterfaceFunctions.h index 8ccbaad756c5d34da5bf9fd7e0ebab7c83a1a2a4..3821faaf2f1a6945bc93e808bb77808709b47454 100644 --- a/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/PythonInterfaceFunctions.h +++ b/Code/Mantid/Framework/PythonAPI/inc/MantidPythonAPI/PythonInterfaceFunctions.h @@ -46,43 +46,43 @@ namespace Mantid // See http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock for more information on the GIL /** - * A simple class that implements an RAII interface for the Python GIL. The GIL is a Python global that needs to be acquired by - * a thread, other than the interpreter thread, that wishs to execute Python code - */ - class PythonLocker + * A simple class that checks whether there is a current thread state, i.e. PyThread_GetDict != NULL, and acquires the GIL if not. + * If it has been aquired then the lock is release on destruction + */ + class PythonGIL { public: ///Constructor - PythonLocker() : m_tstate(PyGILState_UNLOCKED), m_locked(false) + PythonGIL() : m_tstate(NULL), m_gil_state(PyGILState_UNLOCKED), m_locked(false) { + if( !PyThreadState_GetDict() ) + { + m_gil_state = PyGILState_Ensure(); + m_tstate = PyThreadState_GET(); + m_locked = true; + } } - void lock() - { - m_tstate = PyGILState_Ensure(); - m_locked = true; - } ///Destructor - ~PythonLocker() + ~PythonGIL() { if( m_locked ) { - PyGILState_Release(m_tstate); + PyThreadState_Swap(m_tstate); + PyGILState_Release(m_gil_state); } } private: /// Store the thread state - PyGILState_STATE m_tstate; + PyThreadState *m_tstate; + /// Store the GIL state + PyGILState_STATE m_gil_state; /// If we've locked the state bool m_locked; }; /// Handle a Python error state void handlePythonError(const bool with_trace=true); - - /// Check on the current python state - bool pythonIsReady(); - /// A structure t handle default returns for template functions template<typename ResultType> struct DefaultReturn @@ -132,17 +132,10 @@ namespace Mantid static ResultType dispatch(PyObject *object, const std::string & func_name) { - // The order of the GIL lock and ready query are important - PythonLocker gil; - if( FrameworkManagerProxy::requireGIL() ) - { - gil.lock(); - } DefaultReturn<ResultType> default_value; - if( !pythonIsReady() ) return default_value(); - try { + PythonGIL gil; return boost::python::call_method<ResultType>(object, func_name.c_str()); } catch(boost::python::error_already_set&) @@ -159,20 +152,13 @@ namespace Mantid static void dispatch(PyObject *object, const std::string & func_name) { - PythonLocker gil; - if( FrameworkManagerProxy::requireGIL() ) - { - gil.lock(); - } - if( !pythonIsReady() ) return; - PyThreadState *tstate = PyThreadState_GET(); try { + PythonGIL gil; boost::python::call_method<void>(object, func_name.c_str()); } catch(boost::python::error_already_set&) { - PyThreadState_Swap(tstate); handlePythonError(); } } @@ -190,17 +176,10 @@ namespace Mantid static ResultType dispatch(PyObject *object, const std::string & func_name, const ArgType & arg) { - PythonLocker gil; - if( FrameworkManagerProxy::requireGIL() ) - { - gil.lock(); - } - DefaultReturn<ResultType> default_value; - if( !pythonIsReady() ) return; - try { + PythonGIL gil; return boost::python::call_method<ResultType>(object, func_name.c_str(), arg); } catch(boost::python::error_already_set&) @@ -218,15 +197,9 @@ namespace Mantid static void dispatch(PyObject *object, const std::string & func_name, const ArgType & arg) { - PythonLocker gil; - if( FrameworkManagerProxy::requireGIL() ) - { - gil.lock(); - } - if( !pythonIsReady() ) return; - try { + PythonGIL gil; boost::python::call_method<void>(object, func_name.c_str(), arg); } catch(boost::python::error_already_set&) @@ -277,7 +250,7 @@ namespace Mantid template<typename TYPE> boost::python::list toPyList(const std::vector<TYPE> & stdvec) { - return boost::python::list(stdvec); + return boost::python::list(stdvec); } } diff --git a/Code/Mantid/Framework/PythonAPI/src/FrameworkManagerProxy.cpp b/Code/Mantid/Framework/PythonAPI/src/FrameworkManagerProxy.cpp index 851119ba0e45318b8e2a18dd46e476bcfafb7283..394e58e2f9e9d566f0fc6c498f5cd85deecfaa1e 100644 --- a/Code/Mantid/Framework/PythonAPI/src/FrameworkManagerProxy.cpp +++ b/Code/Mantid/Framework/PythonAPI/src/FrameworkManagerProxy.cpp @@ -30,9 +30,6 @@ typedef std::vector<std::string> StringVector; // Initialize the logger Mantid::Kernel::Logger& FrameworkManagerProxy::g_log = Mantid::Kernel::Logger::get("MantidPython"); -// Initialize GIL flag -bool FrameworkManagerProxy::g_gil_required = false; - // Save the flag used on the last creation of the simple API bool FrameworkManagerProxy::g_last_api_flag = false; @@ -371,12 +368,10 @@ void FrameworkManagerProxy::registerPyAlgorithm(boost::python::object pyobj) Mantid::API::CloneableAlgorithm* cppobj = boost::python::extract<Mantid::API::CloneableAlgorithm*>(pyobj); if( cppobj ) { - setGILRequired(true); if( ! Mantid::API::AlgorithmFactory::Instance().storeCloneableAlgorithm(cppobj) ) { g_log.error("Unable to register Python algorithm \"" + cppobj->name() + "\""); } - setGILRequired(false); } else { diff --git a/Code/Mantid/Framework/PythonAPI/src/PythonInterfaceFunctions.cpp b/Code/Mantid/Framework/PythonAPI/src/PythonInterfaceFunctions.cpp index 5a58882812050a15aa35c9045c3b0c0c495bee72..5b468768e56ac0f437d3a22b0b67e115e4d6e2a3 100644 --- a/Code/Mantid/Framework/PythonAPI/src/PythonInterfaceFunctions.cpp +++ b/Code/Mantid/Framework/PythonAPI/src/PythonInterfaceFunctions.cpp @@ -53,14 +53,5 @@ void handlePythonError(const bool with_trace) throw std::runtime_error(msg.str()); } -/** - * Check if the current Python state will allow execution of Python code - */ -bool pythonIsReady() -{ - if( PyThreadState_GET() ) return true; - else return false; -} - } } diff --git a/Code/Mantid/Framework/PythonAPI/src/SimplePythonAPI.cpp b/Code/Mantid/Framework/PythonAPI/src/SimplePythonAPI.cpp index d78d5905398b371f2c490d5a178612326ed1ac2c..3794ead0569791348d69a1879b2926e37ab5ee87 100644 --- a/Code/Mantid/Framework/PythonAPI/src/SimplePythonAPI.cpp +++ b/Code/Mantid/Framework/PythonAPI/src/SimplePythonAPI.cpp @@ -155,11 +155,9 @@ namespace Mantid if( gui ) { - module << " mtd._setGILRequired(True)\n" - << " result = qti.app.mantidUI.runAlgorithmAsync_PyCallback(_algm.name())\n" - << " mtd._setGILRequired(False)\n" - << " if result == False:\n" - << " sys.exit('An error occurred while running %s. See results log for details.' % _algm.name())\n\n"; + module << " result = qti.app.mantidUI.runAlgorithmAsync_PyCallback(_algm.name())\n" + << " if result == False:\n" + << " sys.exit('An error occurred while running %s. See results log for details.' % _algm.name())\n\n"; } else { @@ -514,9 +512,7 @@ namespace Mantid " # Running algorithm\n" " dialog = qti.app.mantidUI.createPropertyInputDialog('Load' , values, kwargs.get('Message',''), final_enabled)\n" " if dialog == True:\n" - " mtd._setGILRequired(True)\n" " result = qti.app.mantidUI.runAlgorithmAsync_PyCallback('Load')\n" - " mtd._setGILRequired(False)\n" " else:\n" " sys.exit('Information: Script execution cancelled')\n" " if result == False:\n" @@ -599,7 +595,7 @@ namespace Mantid } /** - * Write out Python code required to execute an algorithm asynchronously, ensuring the GIL is in the correct state + * Write out Python code required to execute an algorithm asynchronously. * @param output The stream to contain the code * @param alg_name The name of the algorithm * @param prefix A prefix to apply to each line @@ -607,9 +603,7 @@ namespace Mantid void SimplePythonAPI::writeAsyncFunctionCall(std::ostream & output, const std::string & alg_name, const std::string & prefix) { - output << prefix << "mtd._setGILRequired(True)\n" - << prefix << "result = qti.app.mantidUI.runAlgorithmAsync_PyCallback(\"" << alg_name << "\")\n" - << prefix << "mtd._setGILRequired(False)\n"; + output << prefix << "result = qti.app.mantidUI.runAlgorithmAsync_PyCallback(\"" << alg_name << "\")\n"; } /** diff --git a/Code/Mantid/Framework/PythonAPI/src/api_exports.cpp b/Code/Mantid/Framework/PythonAPI/src/api_exports.cpp index 4c894120c35557dd94d21660680f1bb8e18ef5d7..a85bf57d0420a63914f9532e970415cfb74b8f35 100644 --- a/Code/Mantid/Framework/PythonAPI/src/api_exports.cpp +++ b/Code/Mantid/Framework/PythonAPI/src/api_exports.cpp @@ -69,8 +69,6 @@ namespace PythonAPI .def("_workspaceAdded", &FrameworkProxyCallback::default_workspaceAdded) .def("_workspaceStoreCleared", &FrameworkProxyCallback::default_workspaceStoreCleared) .def("_algorithmFactoryUpdated", &FrameworkProxyCallback::default_algorithmFactoryUpdated) - .def("_setGILRequired", &FrameworkManagerProxy::setGILRequired) - .staticmethod("_setGILRequired") ; }