X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=AdaoExchangeLayer.cxx;h=4bc42dd0c24f2813da03752d4726d7efdc9b3864;hb=HEAD;hp=09e396f750aa8a9d1a88002be1d4386040e49c26;hpb=d84c7d6a94dd9b47772ae62cbec1eccf7fc55d0d;p=tools%2Fadao_interface.git diff --git a/AdaoExchangeLayer.cxx b/AdaoExchangeLayer.cxx index 09e396f..4bc42dd 100644 --- a/AdaoExchangeLayer.cxx +++ b/AdaoExchangeLayer.cxx @@ -24,10 +24,7 @@ #include "PyObjectRAII.hxx" #include "Python.h" -#include "py2cpp/py2cpp.hxx" - #include - #include #include #include @@ -168,7 +165,8 @@ class AdaoExchangeLayer::Internal { public: Internal():_context(PyObjectRAII::FromNew(PyDict_New())) - { + { + AutoGIL agil; PyObject *mainmod(PyImport_AddModule("__main__")); PyObject *globals(PyModule_GetDict(mainmod)); PyObject *bltins(PyEval_GetBuiltins()); @@ -212,6 +210,7 @@ AdaoExchangeLayer::AdaoExchangeLayer() AdaoExchangeLayer::~AdaoExchangeLayer() { + AutoGIL agil; delete _internal; } @@ -227,6 +226,38 @@ PyObject *AdaoExchangeLayer::getPythonContext() const return _internal->_context; } +std::string AdaoExchangeLayer::printContext() const +{ + AutoGIL agil; + PyObject *obj(this->getPythonContext()); + if(!PyDict_Check(obj)) + throw AdaoExchangeLayerException("printContext : not a dict !"); + PyObject *key(nullptr), *value(nullptr); + Py_ssize_t pos(0); + std::ostringstream oss; + while( PyDict_Next(obj, &pos, &key, &value) ) + { + if(!PyUnicode_Check(key)) + throw AdaoExchangeLayerException("printContext : not a string as key !"); + oss << PyUnicode_AsUTF8(key) << " = "; + PyObjectRAII reprOfValue(PyObjectRAII::FromNew(PyObject_Repr(value))); + oss << PyUnicode_AsUTF8(reprOfValue); + oss << std::endl; + } + return oss.str(); +} + +/*! + * AdaoExchangeLayer is based on multithreaded paradigm. + * Master thread (thread calling this method) and slave thread (thread calling ADAO algo) + * are calling both python interpretor. Consequence all python calls have to be surrounded with AGIL. + * + * User consequence : To avoid deadlocks this method release GIL. The downstream python calls must be with AGIL. + * + * This method initialize python interpretor if not already the case. + * At the end of this method the lock is released to be ready to perform RAII on GIL + * easily. + */ void AdaoExchangeLayer::initPythonIfNeeded() { if (!Py_IsInitialized()) @@ -239,9 +270,17 @@ void AdaoExchangeLayer::initPythonIfNeeded() PySys_SetArgv(1,TABW); FreeWChar(1,TABW); PyEval_InitThreads(); + delete _internal; + _internal = new Internal; + _internal->_tstate=PyEval_SaveThread(); // release the lock acquired in AdaoExchangeLayer::initPythonIfNeeded by PyEval_InitThreads() + } + else + { + delete _internal; + _internal = new Internal; + if( PyGILState_Check() )// is the GIL already acquired (typically by a PyEval_InitThreads) ? + _internal->_tstate=PyEval_SaveThread(); // release the lock acquired upstream } - delete _internal; - _internal = new Internal; } class Visitor1 : public AdaoModel::PythonLeafVisitor @@ -278,7 +317,7 @@ private: PyObject *_context = nullptr; }; -void AdaoExchangeLayer::loadTemplate(AdaoModel::MainModel *model) +void AdaoExchangeLayer::setFunctionCallbackInModel(AdaoModel::MainModel *model) { AutoGIL agil; const char DECORATOR_FUNC[]="def DecoratorAdao(cppFunc):\n" @@ -305,7 +344,11 @@ void AdaoExchangeLayer::loadTemplate(AdaoModel::MainModel *model) // Visitor1 visitor(this->_internal->_decorator_func,this->_internal->_context); model->visitPythonLeaves(&visitor); - // +} + +void AdaoExchangeLayer::loadTemplate(AdaoModel::MainModel *model) +{ + AutoGIL agil; { std::string sciptPyOfModelMaker(model->pyStr()); PyObjectRAII res(PyObjectRAII::FromNew(PyRun_String(sciptPyOfModelMaker.c_str(),Py_file_input,this->_internal->_context,this->_internal->_context))); @@ -335,7 +378,6 @@ void ExecuteAsync(PyObject *pyExecuteFunction, DataExchangedBetweenThreads *data void AdaoExchangeLayer::execute() { - _internal->_tstate=PyEval_SaveThread(); // release the lock acquired in AdaoExchangeLayer::initPythonIfNeeded by PyEval_InitThreads() _internal->_fut = std::async(std::launch::async,ExecuteAsync,_internal->_execute_func,&_internal->_data_btw_threads); } @@ -364,7 +406,8 @@ void AdaoExchangeLayer::setResult(PyObject *outputAssociated) PyObject *AdaoExchangeLayer::getResult() { _internal->_fut.wait(); - PyEval_RestoreThread(_internal->_tstate); + if(_internal->_tstate) + PyEval_RestoreThread(_internal->_tstate); AutoGIL gil; // now retrieve case.get("Analysis")[-1] PyObjectRAII get_func_of_adao_case(PyObjectRAII::FromNew(PyObject_GetAttrString(_internal->_adao_case,"get")));