/*!
\brief Initialize internal Python interpreter state.
+
+ When calling initState the GIL is not held
+ It must not be held on exit
+
\return \c true on success
*/
bool PyConsole_Interp::initState()
{
- // The GIL is acquired and will be held on initState output
- // It is the caller responsability to release the lock if needed
PyEval_AcquireLock();
_tstate = Py_NewInterpreter(); // create an interpreter and save current state
PySys_SetArgv(PyInterp_Interp::_argc,PyInterp_Interp::_argv); // initialize sys.argv
\brief Initialize python interpeter context.
The GIL is assumed to be held.
- It is the caller responsability caller to acquire the GIL.
- It will still be held on initContext() exit.
+ It is the caller responsability to acquire the GIL.
+ It must still be held on initContext() exit.
\return \c true on success
*/
// Module : SALOME
//
#include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+#include <pythread.h>
#include <cStringIO.h>
#include <structmember.h>
#include <string>
#include <vector>
+#include <map>
#include <iostream>
#define TOP_HISTORY_PY "--- top of history ---"
#define BEGIN_HISTORY_PY "--- begin of history ---"
+// a map to store python thread states that have been created for a given system thread (key=thread id,value=thread state)
+std::map<long,PyThreadState*> currentThreadMap;
+
/*!
\class PyLockWrapper
\brief Python GIL wrapper.
}
/*!
- \brief Desstructor. Automatically releases GIL.
+ \brief Destructor. Automatically releases GIL.
*/
PyLockWrapper::~PyLockWrapper()
{
*/
PyLockWrapper PyInterp_Interp::GetLockWrapper()
{
- return _tstate;
+ if (_tstate->interp == PyInterp_Interp::_interp)
+ return _tstate;
+
+ // If we are here, we have a secondary python interpreter. Try to get a thread state synchronized with the system thread
+ long currentThreadid=PyThread_get_thread_ident(); // the system thread id
+ PyThreadState* theThreadState;
+ if(currentThreadMap.count(currentThreadid) != 0)
+ {
+ //a thread state exists for this thread id
+ PyThreadState* oldThreadState=currentThreadMap[currentThreadid];
+ if(_tstate->interp ==oldThreadState->interp)
+ {
+ //The old thread state has the same python interpreter as this one : reuse the threadstate
+ theThreadState=oldThreadState;
+ }
+ else
+ {
+ //The old thread state has not the same python interpreter as this one : delete the old threadstate and create a new one
+ PyEval_AcquireLock();
+ PyThreadState_Clear(oldThreadState);
+ PyThreadState_Delete(oldThreadState);
+ PyEval_ReleaseLock();
+ theThreadState=PyThreadState_New(_tstate->interp);
+ currentThreadMap[currentThreadid]=theThreadState;
+ }
+ }
+ else
+ {
+ // no old thread state for this thread id : create a new one
+ theThreadState=PyThreadState_New(_tstate->interp);
+ currentThreadMap[currentThreadid]=theThreadState;
+ }
+ return theThreadState;
}
/*
initState();
- PyLockWrapper aLock = GetLockWrapper();
+ PyEval_AcquireThread(_tstate);
initContext();
PyObjWrapper m(PyImport_ImportModule("codeop"));
if(!m) {
PyErr_Print();
+ PyEval_ReleaseThread(_tstate);
return;
}
// All the initRun outputs are redirected to the standard output (console)
initRun();
+ PyEval_ReleaseThread(_tstate);
}
/*!