[Python-Dev] Why is the GIL not in PyInterpreterState? (original) (raw)

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)); }