Salome HOME
Join modifications from branch BR_3_1_0deb
[modules/gui.git] / src / PyInterp / PyInterp_base.cxx
index 525f8771954d346688a7a7d2dadb600c49fdb2cd..69ccefc9d671a8cc6f36f3a2fdf7281157810acc 100644 (file)
 #include <vector>
 
 #include "PyInterp_base.h" // this include must be first (see PyInterp_base.h)!
-#include <Container_init_python.hxx>
 #include <cStringIO.h>
 
-#include <utilities.h>
-
-
 using namespace std;
 
-
-//#ifdef _DEBUG_
-//static int MYDEBUG = 1;
-//static int MYPYDEBUG = 1;
-//#else
-//static int MYDEBUG = 0;
-//static int MYPYDEBUG = 0;
-//#endif
-
-
 PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): 
   myThreadState(theThreadState),
-  mySaveThreadState(KERNEL_PYTHON::_gtstate)
+  mySaveThreadState(0)
 {
-  PyEval_AcquireLock();
-  mySaveThreadState = PyThreadState_Swap(myThreadState); // store previous current in save,
-                                                         // set local in current
-//  if(MYDEBUG) MESSAGE(" PyLockWrapper "<<this<<" aqcuired: new thread state "<<myThreadState<<" ; old thread state "<<mySaveThreadState);
+#if defined(USE_GILSTATE)
+  if (myThreadState->interp == PyInterp_base::_interp) {
+    _savestate = PyGILState_Ensure();
+  } else {
+    PyEval_AcquireThread(myThreadState);
+  }
+#else 
+  PyEval_AcquireThread(myThreadState);
+#endif
 }
 
-
-PyLockWrapper::~PyLockWrapper(){
-  PyThreadState_Swap(mySaveThreadState); // restore previous current (no need to get local,
-  PyEval_ReleaseLock();                  // local thread state* already in _tstate
-//  if(MYDEBUG) MESSAGE(" PyLockWrapper "<<this<<" released: new thread state "<<mySaveThreadState);
+PyLockWrapper::~PyLockWrapper()
+{
+#if defined(USE_GILSTATE)
+  if (myThreadState->interp == PyInterp_base::_interp) {
+    PyGILState_Release(_savestate);
+  } else {
+    PyEval_ReleaseThread(myThreadState);
+  }
+#else 
+  PyEval_ReleaseThread(myThreadState);
+#endif
 }
 
-
 class PyReleaseLock{
 public:
   ~PyReleaseLock(){
-//    if(MYPYDEBUG) MESSAGE("~PyReleaseLock()");
     PyEval_ReleaseLock();
   }
 };
@@ -64,14 +59,16 @@ PyLockWrapper PyInterp_base::GetLockWrapper(){
 }
 
 
-// main python interpreter
+// main python interpreter (static attributes)
 
-//PyThreadState *PyInterp_base::_gtstate = 0; // force 0 before execution
 int PyInterp_base::_argc = 1;
 char* PyInterp_base::_argv[] = {""};
 
 PyObject *PyInterp_base::builtinmodule = NULL;
 
+PyThreadState *PyInterp_base::_gtstate = NULL;
+PyInterpreterState *PyInterp_base::_interp = NULL;
+
 
 /*!
  * basic constructor here : herited classes constructors must call initalize() method
@@ -79,14 +76,10 @@ PyObject *PyInterp_base::builtinmodule = NULL;
  */
 PyInterp_base::PyInterp_base(): _tstate(0), _vout(0), _verr(0), _g(0), _atFirst(true)
 {
-//  if(MYPYDEBUG) MESSAGE("PyInterp_base::PyInterp_base() - this = "<<this);
 }
 
 PyInterp_base::~PyInterp_base()
 {
-//  if(MYPYDEBUG) MESSAGE("PyInterp_base::~PyInterp_base() - this = "<<this);
-  PyLockWrapper aLock(_tstate);
-  //Py_EndInterpreter(_tstate);
 }
 
 
@@ -103,57 +96,52 @@ void PyInterp_base::initialize()
 
   init_python();
   // Here the global lock is released
-//  if(MYPYDEBUG) MESSAGE("PyInterp_base::initialize() - this = "<<this<<"; _gtstate = "<<_gtstate);
-
-  // The lock will be acquired in initState. Make provision to release it on exit
-  PyReleaseLock aReleaseLock;
 
   initState();
+
+  PyLockWrapper aLock= GetLockWrapper();
+
   initContext();
 
   // used to interpret & compile commands
   PyObjWrapper m(PyImport_ImportModule("codeop"));
   if(!m){
-//    INFOS("PyInterp_base::initialize() - PyImport_ImportModule('codeop') failed");
     PyErr_Print();
-    ASSERT(0);
     return;
-  }   
-  
+  }
+
   // Create cStringIO to capture stdout and stderr
   PycString_IMPORT;
-  //PycStringIO = (PycStringIO_CAPI *)xxxPyCObject_Import("cStringIO", "cStringIO_CAPI");
   _vout = PycStringIO->NewOutput(128);
   _verr = PycStringIO->NewOutput(128);
-  
+
   // All the initRun outputs are redirected to the standard output (console)
   initRun();
 }
 
 void PyInterp_base::init_python()
 {
-  /*
-   * Initialize the main state (_gtstate) if not already done
-   * The lock is released on init_python output
-   * It is the caller responsability to acquire it if needed
-   */
-  MESSAGE("PyInterp_base::init_python");
-  ASSERT(KERNEL_PYTHON::_gtstate); // initialisation in main
-  SCRUTE(KERNEL_PYTHON::_gtstate);
-//  if(!_gtstate){
-//    PyReleaseLock aReleaseLock;
-//    Py_Initialize(); // Initialize the interpreter
-//    PyEval_InitThreads(); // Initialize and acquire the global interpreter lock
-//    PySys_SetArgv(_argc,_argv); // initialize sys.argv
-//    _gtstate = PyThreadState_Get();
-//  }
+  _atFirst = false;
+  if (Py_IsInitialized())
+    return;
+
+  // Python is not initialized
+  Py_SetProgramName(_argv[0]);
+  Py_Initialize(); // Initialize the interpreter
+  PySys_SetArgv(_argc, _argv);
+  PyEval_InitThreads(); // Create (and acquire) the interpreter lock
+  _interp = PyThreadState_Get()->interp;
+  _gtstate = PyEval_SaveThread(); // Release global thread state
 }
 
 string PyInterp_base::getbanner()
 {
+ // Should we take the lock ?
+ // PyEval_RestoreThread(_tstate);
   string aBanner("Python ");
   aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
   aBanner = aBanner + "\ntype help to get general information on environment\n";
+  //PyEval_SaveThread();
   return aBanner;
 }
 
@@ -171,7 +159,6 @@ int PyInterp_base::initRun()
   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
 
-//  if(MYPYDEBUG) MESSAGE("PyInterp_base::initRun() - this = "<<this<<"; _verr = "<<_verr<<"; _vout = "<<_vout);
   return 0;
 }
 
@@ -205,11 +192,11 @@ int compile_command(const char *command,PyObject *context)
     return 1;
   }else{
     // Complete and correct text. We evaluate it.
-#ifndef WNT
-    PyObjWrapper r(PyEval_EvalCode(v,context,context));
-#else
-    PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)&v,context,context));
-#endif
+    //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
+    //    PyObjWrapper r(PyEval_EvalCode(v,context,context));
+    //#else
+    PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
+    //#endif
     if(!r){
       // Execution error. We return -1
       PyErr_Print();
@@ -260,15 +247,16 @@ int PyInterp_base::simpleRun(const char *command)
   // Reset redirected outputs before treatment
   PySys_SetObject("stderr",_verr);
   PySys_SetObject("stdout",_vout);
-    
+
   PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
   PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
-  
+
   int ier = compile_command(command,_g);
 
   // Outputs are redirected on standards outputs (console)
   PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
   PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
+
   return ier;
 }
 
@@ -310,4 +298,3 @@ string PyInterp_base::getvout(){
   string aRet(PyString_AsString(v));
   return aRet;
 }