[Python-Dev] Why is the GIL not in PyInterpreterState?
Tobias Oberstein
Tobias.Oberstein@gmx.de
Fri, 7 Feb 2003 14:15:42 +0100
Is there a reason why PyInterpreterState is not defined like so:
typedef struct _is {
..
PyThread_type_lock interpreter_lock;
PyThreadState *_PyThreadState_Current;
..
} PyInterpreterState;
which could be the basis for support of multiple, separated
interpreters within a single process.
I'm coming up with this since I need a scripting language embedded
in a multithreaded server which scales on SMP machines. I've read
through the history of the GIL-issue, and no I can't work around
it (other than using TCL, which I want to avoid at all costs).
please also see:
http://mail.python.org/pipermail/python-list/2003-February/144544.html
Would it be so hard to proceed like indicated below?
Please help a naive geek.
Tobias
PyInterpreterState* Py_Initialize_Ex()
void Py_Finalize_Ex(PyInterpreterState *interp)
PyThreadState* Py_NewInterpreter_Ex(PyInterpreterState *interp)
/* unchanged signature */
void Py_EndInterpreter_Ex(PyThreadState *tstate)
PyThreadState * PyThreadState_Get(PyInterpreterState *interp)
PyObject * PyImport_GetModuleDict(PyThreadState *tstate)
int PyRun_SimpleString_Ex(PyThreadState *tstate, char *command)
#define Py_BEGIN_ALLOW_THREADS(interp) { \
PyThreadState *_save; \
_save = PyEval_SaveThread_Ex(interp);
#define Py_BLOCK_THREADS(interp) PyEval_RestoreThread_Ex(interp,_save);
#define Py_UNBLOCK_THREADS(interp) _save = PyEval_SaveThread_Ex(interp);
#define Py_END_ALLOW_THREADS(interp) PyEval_RestoreThread_Ex(interp,_save);
\
}
PyThreadState *
PyThreadState_Swap_Ex(PyInterpreterState *interp, PyThreadState *new)
{
PyThreadState *old = interp->_PyThreadState_Current;
_PyThreadState_Current = new;
return old;
}
PyThreadState *
PyEval_SaveThread_Ex(PyInterpreterState *interp)
{
PyThreadState *tstate = PyThreadState_Swap(interp, NULL);
if (tstate == NULL)
Py_FatalError("PyEval_SaveThread: NULL tstate");
#ifdef WITH_THREAD
if (interp->interpreter_lock)
PyThread_release_lock(interp->interpreter_lock);
#endif
return tstate;
}
.. and so on ..
for backward compatibility one could do ..
/* essentially the only global to be left .. */
static PyInterpreterState* interp;
void Py_Initialize()
{
interp = Py_Initialize_Ex();
}
void
Py_Finalize(void)
{
Py_Finalize_Ex(interp);
}
PyThreadState *
Py_NewInterpreter(void)
{
return Py_NewInterpreter_Ex(interp);
}
void
Py_EndInterpreter(PyThreadState *tstate)
{
Py_EndInterpreter_Ex(PyThreadState *tstate)
}
PyThreadState *
PyThreadState_Get(void)
{
return PyThreadState_Get(interp)
}
int
PyRun_SimpleString(char *command)
{
return PyRun_SimpleString_Ex(PyThreadState_Get(interp), command);
}
PyObject *
PyImport_GetModuleDict(void)
{
return PyImport_GetModuleDict(PyThreadState_Get(interp));
}