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