From: Anthony Geay Date: Fri, 12 Jul 2019 14:30:14 +0000 (+0200) Subject: Ready pour l export X-Git-Tag: V9_4_0~7 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=903d822879ba1479f5d8a68579f6a02090a07475;p=tools%2Fadao_interface.git Ready pour l export --- diff --git a/AdaoExchangeLayer.cxx b/AdaoExchangeLayer.cxx new file mode 100644 index 0000000..9a101a4 --- /dev/null +++ b/AdaoExchangeLayer.cxx @@ -0,0 +1,390 @@ +// Copyright (C) 2019 EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// Author: Anthony Geay, anthony.geay@edf.fr, EDF R&D + +#include "AdaoExchangeLayer.hxx" +#include "AdaoExchangeLayerException.hxx" +#include "AdaoModelKeyVal.hxx" +#include "PyObjectRAII.hxx" +#include "Python.h" + +#include "py2cpp/py2cpp.hxx" + +#include + +#include +#include +#include +#include +#include +#include + +struct DataExchangedBetweenThreads // data written by subthread and read by calling thread +{ +public: + DataExchangedBetweenThreads(); + ~DataExchangedBetweenThreads(); +public: + sem_t _sem; + sem_t _sem_result_is_here; + volatile bool _finished = false; + volatile PyObject *_data = nullptr; +}; + +///////////////////////////////////////////// + +struct AdaoCallbackSt +{ + PyObject_HEAD + DataExchangedBetweenThreads *_data; +}; + +static PyObject *adaocallback_call(AdaoCallbackSt *self, PyObject *args, PyObject *kw) +{ + if(!PyTuple_Check(args)) + throw AdaoExchangeLayerException("Input args is not a tuple as expected !"); + if(PyTuple_Size(args)!=1) + throw AdaoExchangeLayerException("Input args is not a tuple of size 1 as expected !"); + PyObjectRAII zeobj(PyObjectRAII::FromBorrowed(PyTuple_GetItem(args,0))); + if(zeobj.isNull()) + throw AdaoExchangeLayerException("Retrieve of elt #0 of input tuple has failed !"); + volatile PyObject *ret(nullptr); + PyThreadState *tstate(PyEval_SaveThread());// GIL is acquired (see ExecuteAsync). Before entering into non python section. Release lock + { + self->_data->_finished = false; + self->_data->_data = zeobj; + sem_post(&self->_data->_sem); + sem_wait(&self->_data->_sem_result_is_here); + ret = self->_data->_data; + } + PyEval_RestoreThread(tstate);//End of parallel section. Reaquire the GIL and restore the thread state + return (PyObject *)ret; +} + +static int adaocallback___init__(PyObject *self, PyObject *args, PyObject *kwargs) { return 0; } + +static PyObject *adaocallback___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + return (PyObject *)( type->tp_alloc(type, 0) ); +} + +static void adaocallback_dealloc(PyObject *self) +{ + Py_TYPE(self)->tp_free(self); +} + +PyTypeObject AdaoCallbackType = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "adaocallbacktype", + sizeof(AdaoCallbackSt), + 0, + adaocallback_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)adaocallback_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + adaocallback___init__, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + adaocallback___new__, /*tp_new*/ + PyObject_GC_Del, /*tp_free*/ +}; + +///////////////////////////////////////////// + +DataExchangedBetweenThreads::DataExchangedBetweenThreads() +{ + if(sem_init(&_sem,0,0)!=0)// put value to 0 to lock by default + throw AdaoExchangeLayerException("Internal constructor : Error on initialization of semaphore !"); + if(sem_init(&_sem_result_is_here,0,0)!=0)// put value to 0 to lock by default + throw AdaoExchangeLayerException("Internal constructor : Error on initialization of semaphore !"); +} + +DataExchangedBetweenThreads::~DataExchangedBetweenThreads() +{ + sem_destroy(&_sem); + sem_destroy(&_sem_result_is_here); +} + +class AdaoCallbackKeeper +{ +public: + void assign(AdaoCallbackSt *pt, DataExchangedBetweenThreads *data) + { + release(); + _pt = pt; + _pt->_data = data; + } + PyObject *getPyObject() const { return reinterpret_cast(_pt); } + ~AdaoCallbackKeeper() { release(); } +private: + void release() { if(_pt) { Py_XDECREF(_pt); } } +private: + AdaoCallbackSt *_pt = nullptr; +}; + +class AdaoExchangeLayer::Internal +{ +public: + Internal():_context(PyObjectRAII::FromNew(PyDict_New())) + { + PyObject *mainmod(PyImport_AddModule("__main__")); + PyObject *globals(PyModule_GetDict(mainmod)); + PyObject *bltins(PyEval_GetBuiltins()); + PyDict_SetItemString(_context,"__builtins__",bltins); + } +public: + PyObjectRAII _context; + PyObjectRAII _generate_case_func; + PyObjectRAII _decorator_func; + PyObjectRAII _adao_case; + PyObjectRAII _execute_func; + AdaoCallbackKeeper _py_call_back; + std::future< void > _fut; + PyThreadState *_tstate = nullptr; + DataExchangedBetweenThreads _data_btw_threads; +}; + +wchar_t **ConvertToWChar(int argc, const char *argv[]) +{ + wchar_t **ret(new wchar_t*[argc]); + for(int i=0;i_context; +} + +void AdaoExchangeLayer::initPythonIfNeeded() +{ + if (!Py_IsInitialized()) + { + const char *TAB[]={"AdaoExchangeLayer"}; + wchar_t **TABW(ConvertToWChar(1,TAB)); + // Python is not initialized + Py_SetProgramName(const_cast(TABW[0])); + Py_Initialize(); // Initialize the interpreter + PySys_SetArgv(1,TABW); + FreeWChar(1,TABW); + PyEval_InitThreads(); + } + delete _internal; + _internal = new Internal; +} + +class Visitor1 : public AdaoModel::PythonLeafVisitor +{ +public: + Visitor1(PyObjectRAII func, PyObject *context):_func(func),_context(context) + { + } + + void visit(AdaoModel::MainModel *godFather, AdaoModel::PyObjKeyVal *obj) override + { + if(obj->getKey()=="Matrix" || obj->getKey()=="DiagonalSparseMatrix") + { + std::ostringstream oss; oss << "__" << _cnt++; + std::string varname(oss.str()); + obj->setVal(Py_None); + PyDict_SetItemString(_context,varname.c_str(),Py_None); + obj->setVarName(varname); + return ; + } + if(obj->getKey()=="OneFunction") + { + std::ostringstream oss; oss << "__" << _cnt++; + std::string varname(oss.str()); + obj->setVal(_func); + PyDict_SetItemString(_context,varname.c_str(),_func); + obj->setVarName(varname); + return ; + } + } +private: + unsigned int _cnt = 0; + PyObjectRAII _func; + PyObject *_context = nullptr; +}; + +void AdaoExchangeLayer::loadTemplate(AdaoModel::MainModel *model) +{ + const char DECORATOR_FUNC[]="def DecoratorAdao(cppFunc):\n" + " def evaluator( xserie ):\n" + " import numpy as np\n" + " yserie = [np.array(elt) for elt in cppFunc(xserie)]\n" + " return yserie\n" + " return evaluator\n"; + this->_internal->_py_call_back.assign(PyObject_GC_New(AdaoCallbackSt,&AdaoCallbackType), + &this->_internal->_data_btw_threads); + PyObject *callbackPyObj(this->_internal->_py_call_back.getPyObject()); + // + { + PyObjectRAII res(PyObjectRAII::FromNew(PyRun_String(DECORATOR_FUNC,Py_file_input,this->_internal->_context,this->_internal->_context))); + PyObjectRAII decoratorGenerator( PyObjectRAII::FromBorrowed(PyDict_GetItemString(this->_internal->_context,"DecoratorAdao")) ); + if(decoratorGenerator.isNull()) + throw AdaoExchangeLayerException("Fail to locate DecoratorAdao function !"); + PyObjectRAII args(PyObjectRAII::FromNew(PyTuple_New(1))); + { PyTuple_SetItem(args,0,callbackPyObj); Py_XINCREF(callbackPyObj); } + this->_internal->_decorator_func = PyObjectRAII::FromNew(PyObject_CallObject(decoratorGenerator,args)); + if(this->_internal->_decorator_func.isNull()) + throw AdaoExchangeLayerException("Fail to generate result of DecoratorAdao function !"); + } + // + Visitor1 visitor(this->_internal->_decorator_func,this->_internal->_context); + model->visitPythonLeaves(&visitor); + // + { + std::string sciptPyOfModelMaker(model->pyStr()); + PyObjectRAII res(PyObjectRAII::FromNew(PyRun_String(sciptPyOfModelMaker.c_str(),Py_file_input,this->_internal->_context,this->_internal->_context))); + PyErr_Print(); + _internal->_adao_case = PyObjectRAII::FromNew(PyDict_GetItemString(this->_internal->_context,"case")); + } + if(_internal->_adao_case.isNull()) + throw AdaoExchangeLayerException("Fail to generate ADAO case object !"); + // + _internal->_execute_func=PyObjectRAII::FromNew(PyObject_GetAttrString(_internal->_adao_case,"execute")); + if(_internal->_execute_func.isNull()) + throw AdaoExchangeLayerException("Fail to locate execute function of ADAO case object !"); +} + +void ExecuteAsync(PyObject *pyExecuteFunction, DataExchangedBetweenThreads *data) +{ + AutoGIL gil; // launched in a separed thread -> protect python calls + PyObjectRAII args(PyObjectRAII::FromNew(PyTuple_New(0))); + PyObjectRAII nullRes(PyObjectRAII::FromNew(PyObject_CallObject(pyExecuteFunction,args)));// go to adaocallback_call + PyErr_Print(); + data->_finished = true; + data->_data = nullptr; + sem_post(&data->_sem); +} + +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); +} + +bool AdaoExchangeLayer::next(PyObject *& inputRequested) +{ + sem_wait(&_internal->_data_btw_threads._sem); + if(_internal->_data_btw_threads._finished) + { + inputRequested = nullptr; + return false; + } + else + { + inputRequested = (PyObject *)_internal->_data_btw_threads._data; + return true; + } +} + +void AdaoExchangeLayer::setResult(PyObject *outputAssociated) +{ + _internal->_data_btw_threads._data = outputAssociated; + _internal->_data_btw_threads._finished = false; + sem_post(&_internal->_data_btw_threads._sem_result_is_here); +} + +PyObject *AdaoExchangeLayer::getResult() +{ + _internal->_fut.wait(); + 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"))); + if(get_func_of_adao_case.isNull()) + throw AdaoExchangeLayerException("Fail to locate \"get\" method from ADAO case !"); + PyObjectRAII all_intermediate_results; + {// retrieve return data from case.get("Analysis") + PyObjectRAII args(PyObjectRAII::FromNew(PyTuple_New(1))); + PyTuple_SetItem(args,0,PyUnicode_FromString("Analysis")); + all_intermediate_results=PyObjectRAII::FromNew(PyObject_CallObject(get_func_of_adao_case,args)); + if(all_intermediate_results.isNull()) + throw AdaoExchangeLayerException("Fail to retrieve result of case.get(\"Analysis\") !"); + } + PyObjectRAII optimum; + { + PyObjectRAII param(PyObjectRAII::FromNew(PyLong_FromLong(-1))); + optimum=PyObjectRAII::FromNew(PyObject_GetItem(all_intermediate_results,param)); + if(optimum.isNull()) + throw AdaoExchangeLayerException("Fail to retrieve result of last element of case.get(\"Analysis\") !"); + } + /*PyObjectRAII code(PyObjectRAII::FromNew(Py_CompileString("case.get(\"Analysis\")[-1]","retrieve result",Py_file_input))); + if(code.isNull()) + throw AdaoExchangeLayerException("Fail to compile code to retrieve result after ADAO computation !"); + PyObjectRAII res(PyObjectRAII::FromNew(PyEval_EvalCode(code,_internal->_context,_internal->_context)));*/ + return optimum.retn(); +} diff --git a/AdaoExchangeLayer.hxx b/AdaoExchangeLayer.hxx new file mode 100644 index 0000000..dbb3dba --- /dev/null +++ b/AdaoExchangeLayer.hxx @@ -0,0 +1,49 @@ +// Copyright (C) 2019 EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// Author: Anthony Geay, anthony.geay@edf.fr, EDF R&D + +#pragma once + +#include "Python.h" + +class AdaoCallbackSt; + +namespace AdaoModel +{ + class MainModel; +} + +class AdaoExchangeLayer +{ + class Internal; +public: + AdaoExchangeLayer(); + ~AdaoExchangeLayer(); + PyObject *getPythonContext() const; + void init(); + void loadTemplate(AdaoModel::MainModel *model); + void execute(); + bool next(PyObject *& inputRequested); + void setResult(PyObject *outputAssociated); + PyObject *getResult(); +private: + void initPythonIfNeeded(); +private: + Internal *_internal = nullptr; +}; diff --git a/AdaoExchangeLayer4Quintet.cxx b/AdaoExchangeLayer4Quintet.cxx deleted file mode 100644 index 4b82af4..0000000 --- a/AdaoExchangeLayer4Quintet.cxx +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright (C) 2019 EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -// Author: Anthony Geay, anthony.geay@edf.fr, EDF R&D - -#include "AdaoExchangeLayer4Quintet.hxx" -#include "AdaoExchangeLayerException.hxx" -#include "AdaoModelKeyVal.hxx" -#include "PyObjectRAII.hxx" -#include "Python.h" - -#include "py2cpp/py2cpp.hxx" - -#include - -#include -#include -#include -#include -#include -#include - -struct DataExchangedBetweenThreads // data written by subthread and read by calling thread -{ -public: - DataExchangedBetweenThreads(); - ~DataExchangedBetweenThreads(); -public: - sem_t _sem; - sem_t _sem_result_is_here; - volatile bool _finished = false; - volatile PyObject *_data = nullptr; -}; - -///////////////////////////////////////////// - -struct AdaoCallbackSt -{ - PyObject_HEAD - DataExchangedBetweenThreads *_data; -}; - -static PyObject *adaocallback_call(AdaoCallbackSt *self, PyObject *args, PyObject *kw) -{ - if(!PyTuple_Check(args)) - throw AdaoExchangeLayerException("Input args is not a tuple as expected !"); - if(PyTuple_Size(args)!=1) - throw AdaoExchangeLayerException("Input args is not a tuple of size 1 as expected !"); - PyObjectRAII zeobj(PyObjectRAII::FromBorrowed(PyTuple_GetItem(args,0))); - if(zeobj.isNull()) - throw AdaoExchangeLayerException("Retrieve of elt #0 of input tuple has failed !"); - volatile PyObject *ret(nullptr); - PyThreadState *tstate(PyEval_SaveThread());// GIL is acquired (see ExecuteAsync). Before entering into non python section. Release lock - { - self->_data->_finished = false; - self->_data->_data = zeobj; - sem_post(&self->_data->_sem); - sem_wait(&self->_data->_sem_result_is_here); - ret = self->_data->_data; - } - PyEval_RestoreThread(tstate);//End of parallel section. Reaquire the GIL and restore the thread state - return (PyObject *)ret; -} - -static int adaocallback___init__(PyObject *self, PyObject *args, PyObject *kwargs) { return 0; } - -static PyObject *adaocallback___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - return (PyObject *)( type->tp_alloc(type, 0) ); -} - -static void adaocallback_dealloc(PyObject *self) -{ - Py_TYPE(self)->tp_free(self); -} - -PyTypeObject AdaoCallbackType = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "adaocallbacktype", - sizeof(AdaoCallbackSt), - 0, - adaocallback_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)adaocallback_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - adaocallback___init__, /*tp_init*/ - PyType_GenericAlloc, /*tp_alloc*/ - adaocallback___new__, /*tp_new*/ - PyObject_GC_Del, /*tp_free*/ -}; - -///////////////////////////////////////////// - -DataExchangedBetweenThreads::DataExchangedBetweenThreads() -{ - if(sem_init(&_sem,0,0)!=0)// put value to 0 to lock by default - throw AdaoExchangeLayerException("Internal constructor : Error on initialization of semaphore !"); - if(sem_init(&_sem_result_is_here,0,0)!=0)// put value to 0 to lock by default - throw AdaoExchangeLayerException("Internal constructor : Error on initialization of semaphore !"); -} - -DataExchangedBetweenThreads::~DataExchangedBetweenThreads() -{ - sem_destroy(&_sem); - sem_destroy(&_sem_result_is_here); -} - -class AdaoCallbackKeeper -{ -public: - void assign(AdaoCallbackSt *pt, DataExchangedBetweenThreads *data) - { - release(); - _pt = pt; - _pt->_data = data; - } - PyObject *getPyObject() const { return reinterpret_cast(_pt); } - ~AdaoCallbackKeeper() { release(); } -private: - void release() { if(_pt) { Py_XDECREF(_pt); } } -private: - AdaoCallbackSt *_pt = nullptr; -}; - -class AdaoExchangeLayer4Quintet::Internal -{ -public: - Internal():_context(PyObjectRAII::FromNew(PyDict_New())) - { - PyObject *mainmod(PyImport_AddModule("__main__")); - PyObject *globals(PyModule_GetDict(mainmod)); - PyObject *bltins(PyEval_GetBuiltins()); - PyDict_SetItemString(_context,"__builtins__",bltins); - } -public: - PyObjectRAII _context; - PyObjectRAII _generate_case_func; - PyObjectRAII _decorator_func; - PyObjectRAII _adao_case; - PyObjectRAII _execute_func; - AdaoCallbackKeeper _py_call_back; - std::future< void > _fut; - PyThreadState *_tstate = nullptr; - DataExchangedBetweenThreads _data_btw_threads; -}; - -wchar_t **ConvertToWChar(int argc, const char *argv[]) -{ - wchar_t **ret(new wchar_t*[argc]); - for(int i=0;i_context; -} - -void AdaoExchangeLayer4Quintet::initPythonIfNeeded() -{ - if (!Py_IsInitialized()) - { - const char *TAB[]={"AdaoExchangeLayer4Quintet"}; - wchar_t **TABW(ConvertToWChar(1,TAB)); - // Python is not initialized - Py_SetProgramName(const_cast(TABW[0])); - Py_Initialize(); // Initialize the interpreter - PySys_SetArgv(1,TABW); - FreeWChar(1,TABW); - PyEval_InitThreads(); - } - delete _internal; - _internal = new Internal; -} - -class Visitor1 : public AdaoModel::PythonLeafVisitor -{ -public: - Visitor1(PyObjectRAII func, PyObject *context):_func(func),_context(context) - { - } - - void visit(AdaoModel::MainModel *godFather, AdaoModel::PyObjKeyVal *obj) override - { - if(obj->getKey()=="Matrix" || obj->getKey()=="DiagonalSparseMatrix") - { - std::ostringstream oss; oss << "__" << _cnt++; - std::string varname(oss.str()); - obj->setVal(Py_None); - PyDict_SetItemString(_context,varname.c_str(),Py_None); - obj->setVarName(varname); - return ; - } - if(obj->getKey()=="OneFunction") - { - std::ostringstream oss; oss << "__" << _cnt++; - std::string varname(oss.str()); - obj->setVal(_func); - PyDict_SetItemString(_context,varname.c_str(),_func); - obj->setVarName(varname); - return ; - } - } -private: - unsigned int _cnt = 0; - PyObjectRAII _func; - PyObject *_context = nullptr; -}; - -void AdaoExchangeLayer4Quintet::loadTemplate(AdaoModel::MainModel *model) -{ - const char DECORATOR_FUNC[]="def DecoratorAdao(cppFunc):\n" - " def evaluator( xserie ):\n" - " import numpy as np\n" - " yserie = [np.array(elt) for elt in cppFunc(xserie)]\n" - " return yserie\n" - " return evaluator\n"; - this->_internal->_py_call_back.assign(PyObject_GC_New(AdaoCallbackSt,&AdaoCallbackType), - &this->_internal->_data_btw_threads); - PyObject *callbackPyObj(this->_internal->_py_call_back.getPyObject()); - // - { - PyObjectRAII res(PyObjectRAII::FromNew(PyRun_String(DECORATOR_FUNC,Py_file_input,this->_internal->_context,this->_internal->_context))); - PyObjectRAII decoratorGenerator( PyObjectRAII::FromBorrowed(PyDict_GetItemString(this->_internal->_context,"DecoratorAdao")) ); - if(decoratorGenerator.isNull()) - throw AdaoExchangeLayerException("Fail to locate DecoratorAdao function !"); - PyObjectRAII args(PyObjectRAII::FromNew(PyTuple_New(1))); - { PyTuple_SetItem(args,0,callbackPyObj); Py_XINCREF(callbackPyObj); } - this->_internal->_decorator_func = PyObjectRAII::FromNew(PyObject_CallObject(decoratorGenerator,args)); - if(this->_internal->_decorator_func.isNull()) - throw AdaoExchangeLayerException("Fail to generate result of DecoratorAdao function !"); - } - // - Visitor1 visitor(this->_internal->_decorator_func,this->_internal->_context); - model->visitPythonLeaves(&visitor); - // - { - std::string sciptPyOfModelMaker(model->pyStr()); - PyObjectRAII res(PyObjectRAII::FromNew(PyRun_String(sciptPyOfModelMaker.c_str(),Py_file_input,this->_internal->_context,this->_internal->_context))); - PyErr_Print(); - _internal->_adao_case = PyObjectRAII::FromNew(PyDict_GetItemString(this->_internal->_context,"case")); - } - if(_internal->_adao_case.isNull()) - throw AdaoExchangeLayerException("Fail to generate ADAO case object !"); - // - _internal->_execute_func=PyObjectRAII::FromNew(PyObject_GetAttrString(_internal->_adao_case,"execute")); - if(_internal->_execute_func.isNull()) - throw AdaoExchangeLayerException("Fail to locate execute function of ADAO case object !"); -} - -void ExecuteAsync(PyObject *pyExecuteFunction, DataExchangedBetweenThreads *data) -{ - AutoGIL gil; // launched in a separed thread -> protect python calls - PyObjectRAII args(PyObjectRAII::FromNew(PyTuple_New(0))); - PyObjectRAII nullRes(PyObjectRAII::FromNew(PyObject_CallObject(pyExecuteFunction,args)));// go to adaocallback_call - PyErr_Print(); - data->_finished = true; - data->_data = nullptr; - sem_post(&data->_sem); -} - -void AdaoExchangeLayer4Quintet::execute() -{ - _internal->_tstate=PyEval_SaveThread(); // release the lock acquired in AdaoExchangeLayer4Quintet::initPythonIfNeeded by PyEval_InitThreads() - _internal->_fut = std::async(std::launch::async,ExecuteAsync,_internal->_execute_func,&_internal->_data_btw_threads); -} - -bool AdaoExchangeLayer4Quintet::next(PyObject *& inputRequested) -{ - sem_wait(&_internal->_data_btw_threads._sem); - if(_internal->_data_btw_threads._finished) - { - inputRequested = nullptr; - return false; - } - else - { - inputRequested = (PyObject *)_internal->_data_btw_threads._data; - return true; - } -} - -void AdaoExchangeLayer4Quintet::setResult(PyObject *outputAssociated) -{ - _internal->_data_btw_threads._data = outputAssociated; - _internal->_data_btw_threads._finished = false; - sem_post(&_internal->_data_btw_threads._sem_result_is_here); -} - -PyObject *AdaoExchangeLayer4Quintet::getResult() -{ - _internal->_fut.wait(); - 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"))); - if(get_func_of_adao_case.isNull()) - throw AdaoExchangeLayerException("Fail to locate \"get\" method from ADAO case !"); - PyObjectRAII all_intermediate_results; - {// retrieve return data from case.get("Analysis") - PyObjectRAII args(PyObjectRAII::FromNew(PyTuple_New(1))); - PyTuple_SetItem(args,0,PyUnicode_FromString("Analysis")); - all_intermediate_results=PyObjectRAII::FromNew(PyObject_CallObject(get_func_of_adao_case,args)); - if(all_intermediate_results.isNull()) - throw AdaoExchangeLayerException("Fail to retrieve result of case.get(\"Analysis\") !"); - } - PyObjectRAII optimum; - { - PyObjectRAII param(PyObjectRAII::FromNew(PyLong_FromLong(-1))); - optimum=PyObjectRAII::FromNew(PyObject_GetItem(all_intermediate_results,param)); - if(optimum.isNull()) - throw AdaoExchangeLayerException("Fail to retrieve result of last element of case.get(\"Analysis\") !"); - } - /*PyObjectRAII code(PyObjectRAII::FromNew(Py_CompileString("case.get(\"Analysis\")[-1]","retrieve result",Py_file_input))); - if(code.isNull()) - throw AdaoExchangeLayerException("Fail to compile code to retrieve result after ADAO computation !"); - PyObjectRAII res(PyObjectRAII::FromNew(PyEval_EvalCode(code,_internal->_context,_internal->_context)));*/ - return optimum.retn(); -} diff --git a/AdaoExchangeLayer4Quintet.hxx b/AdaoExchangeLayer4Quintet.hxx deleted file mode 100644 index 0ef1405..0000000 --- a/AdaoExchangeLayer4Quintet.hxx +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2019 EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -// Author: Anthony Geay, anthony.geay@edf.fr, EDF R&D - -#pragma once - -#include "Python.h" - -class AdaoCallbackSt; - -namespace AdaoModel -{ - class MainModel; -} - -class AdaoExchangeLayer4Quintet -{ - class Internal; -public: - AdaoExchangeLayer4Quintet(); - ~AdaoExchangeLayer4Quintet(); - PyObject *getPythonContext() const; - void init(); - void loadTemplate(AdaoModel::MainModel *model); - void execute(); - bool next(PyObject *& inputRequested); - void setResult(PyObject *outputAssociated); - PyObject *getResult(); -private: - void initPythonIfNeeded(); -private: - Internal *_internal = nullptr; -}; diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b6d503..8a07675 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ # Author: Anthony Geay, anthony.geay@edf.fr, EDF R&D cmake_minimum_required(VERSION 2.6) -project(AdaoExchangeLayer4Quintet) +project(AdaoExchangeLayer) ## @@ -61,10 +61,10 @@ include_directories( ${PY2CPP_INCLUDE_DIR} ${CPPUNIT_INCLUDE_DIRS} ) -set(adaoexchange_SOURCES AdaoExchangeLayer4Quintet.cxx AdaoModelKeyVal.cxx) +set(adaoexchange_SOURCES AdaoExchangeLayer.cxx AdaoModelKeyVal.cxx) add_library(adaoexchange ${adaoexchange_SOURCES}) target_link_libraries(adaoexchange ${PYTHON_LIBRARIES}) -install(FILES AdaoExchangeLayer4Quintet.hxx PyObjectRAII.hxx AdaoExchangeLayerException.hxx AdaoModelKeyVal.hxx DESTINATION include) +install(FILES AdaoExchangeLayer.hxx PyObjectRAII.hxx AdaoExchangeLayerException.hxx AdaoModelKeyVal.hxx DESTINATION include) install(TARGETS adaoexchange DESTINATION lib) ## diff --git a/TestAdaoExchange.cxx b/TestAdaoExchange.cxx index 803cbc1..f0d7150 100644 --- a/TestAdaoExchange.cxx +++ b/TestAdaoExchange.cxx @@ -20,7 +20,7 @@ #include "TestAdaoExchange.hxx" -#include "AdaoExchangeLayer4Quintet.hxx" +#include "AdaoExchangeLayer.hxx" #include "AdaoExchangeLayerException.hxx" #include "AdaoModelKeyVal.hxx" #include "PyObjectRAII.hxx" @@ -121,7 +121,7 @@ void AdaoExchangeTest::test3DVar() { NonParallelFunctor functor(funcBase); MainModel mm; - AdaoExchangeLayer4Quintet adao; + AdaoExchangeLayer adao; adao.init(); // For bounds, Background/Vector, Observation/Vector Visitor2 visitorPythonObj(adao.getPythonContext()); @@ -175,7 +175,7 @@ void AdaoExchangeTest::testBlue() TestBlueVisitor vis; mm.visitAll(&vis); // - AdaoExchangeLayer4Quintet adao; + AdaoExchangeLayer adao; adao.init(); // For bounds, Background/Vector, Observation/Vector Visitor2 visitorPythonObj(adao.getPythonContext()); @@ -228,7 +228,7 @@ void AdaoExchangeTest::testNonLinearLeastSquares() TestNonLinearLeastSquaresVisitor vis; mm.visitAll(&vis); // - AdaoExchangeLayer4Quintet adao; + AdaoExchangeLayer adao; adao.init(); // For bounds, Background/Vector, Observation/Vector Visitor2 visitorPythonObj(adao.getPythonContext()); @@ -265,7 +265,7 @@ void AdaoExchangeTest::testCasCrue() { NonParallelFunctor functor(funcCrue); MainModel mm; - AdaoExchangeLayer4Quintet adao; + AdaoExchangeLayer adao; adao.init(); // For bounds, Background/Vector, Observation/Vector VisitorCruePython visitorPythonObj(adao.getPythonContext());