Salome HOME
Key point. OK for GUI persalys + python persalys + Test C++. Tests follow new explici...
authorAnthony Geay <anthony.geay@edf.fr>
Wed, 25 Sep 2019 09:21:22 +0000 (11:21 +0200)
committerAnthony Geay <anthony.geay@edf.fr>
Wed, 25 Sep 2019 09:21:22 +0000 (11:21 +0200)
AdaoExchangeLayer.cxx
README.txt
TestAdaoExchange.cxx

index 09e396f750aa8a9d1a88002be1d4386040e49c26..c5c15b8c1add3af5167d6018ae4633911eef6f8b 100644 (file)
@@ -168,7 +168,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());
@@ -227,6 +228,17 @@ PyObject *AdaoExchangeLayer::getPythonContext() const
   return _internal->_context;
 }
 
+/*!
+ * 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 +251,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
@@ -335,7 +355,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 +383,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")));
index a7ac090d37a69c86240018367aa05cf11759998b..5ca707663e6826cac01b53ba8fd9d2d03f9c86a8 100644 (file)
@@ -10,6 +10,10 @@ AdaoExchangeLayer manage the GIL (using AutoGIL) in its implementation.
 
 Consequence the AdaoExchangeLayer instance should NOT be surrounded by GIL protection.
 
+Consequence : AdaoExchangeLayer::initPythonIfNeeded initializes the python interpretor (if not already done) and let the GIL released to manage all python caller threads easily
+
+Consequence : Using ADAO interface implies to protect python calls
+
 ############## user GIL management in AdaoModel::MainModel
 
 The custom MainModel overloading should be GIL protected by the user.
index f0d715048f4acadbd5c113a52d27492d0cb480f0..30d29490b85bec16256ccf92d56f8614c106d9da 100644 (file)
@@ -125,7 +125,10 @@ void AdaoExchangeTest::test3DVar()
   adao.init();
   // For bounds, Background/Vector, Observation/Vector
   Visitor2 visitorPythonObj(adao.getPythonContext());
-  mm.visitPythonLeaves(&visitorPythonObj);
+  {
+    AutoGIL agil;
+    mm.visitPythonLeaves(&visitorPythonObj);
+  }
   //
   adao.loadTemplate(&mm);
   //
@@ -179,7 +182,10 @@ void AdaoExchangeTest::testBlue()
   adao.init();
   // For bounds, Background/Vector, Observation/Vector
   Visitor2 visitorPythonObj(adao.getPythonContext());
-  mm.visitPythonLeaves(&visitorPythonObj);
+  {
+    AutoGIL agil;
+    mm.visitPythonLeaves(&visitorPythonObj);
+  }
   //
   adao.loadTemplate(&mm);
   //
@@ -232,7 +238,10 @@ void AdaoExchangeTest::testNonLinearLeastSquares()
   adao.init();
   // For bounds, Background/Vector, Observation/Vector
   Visitor2 visitorPythonObj(adao.getPythonContext());
-  mm.visitPythonLeaves(&visitorPythonObj);
+  {
+    AutoGIL agil;
+    mm.visitPythonLeaves(&visitorPythonObj);
+  }
   //
   adao.loadTemplate(&mm);
   //
@@ -269,7 +278,10 @@ void AdaoExchangeTest::testCasCrue()
   adao.init();
   // For bounds, Background/Vector, Observation/Vector
   VisitorCruePython visitorPythonObj(adao.getPythonContext());
-  mm.visitPythonLeaves(&visitorPythonObj);
+  {
+    AutoGIL agil;
+    mm.visitPythonLeaves(&visitorPythonObj);
+  }
   //
   adao.loadTemplate(&mm);
   //