#include "PyObjectRAII.hxx"
#include "Python.h"
-#include "py2cpp/py2cpp.hxx"
-
#include <semaphore.h>
-
#include <iostream>
#include <sstream>
#include <clocale>
{
public:
Internal():_context(PyObjectRAII::FromNew(PyDict_New()))
- {
+ {
+ AutoGIL agil;
PyObject *mainmod(PyImport_AddModule("__main__"));
PyObject *globals(PyModule_GetDict(mainmod));
PyObject *bltins(PyEval_GetBuiltins());
AdaoExchangeLayer::~AdaoExchangeLayer()
{
+ AutoGIL agil;
delete _internal;
}
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())
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
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"
" def evaluator( xserie ):\n"
" import numpy as np\n"
//
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)));
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);
}
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")));