mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
Patch by Jonathan Giddy (with some cleanup by me) to always use the
thread state of the thread calling mainloop() (or another event handling function) rather than the thread state of the function that created the client data structure.
This commit is contained in:
parent
afd974c2ab
commit
dc1adabcb8
1 changed files with 30 additions and 22 deletions
|
@ -157,14 +157,14 @@ PERFORMANCE OF THIS SOFTWARE.
|
||||||
the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
|
the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
|
||||||
releases the Tcl lock.
|
releases the Tcl lock.
|
||||||
|
|
||||||
By contrast, ENTER_PYTHON(tstate) and LEAVE_PYTHON are used in Tcl event
|
By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
|
||||||
handlers when the handler needs to use Python. Such event handlers are
|
handlers when the handler needs to use Python. Such event handlers are
|
||||||
entered while the lock for Tcl is held; the event handler presumably needs
|
entered while the lock for Tcl is held; the event handler presumably needs
|
||||||
to use Python. ENTER_PYTHON(tstate) releases the lock for Tcl and acquires
|
to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
|
||||||
the Python interpreter lock, restoring the appropriate thread state, and
|
the Python interpreter lock, restoring the appropriate thread state, and
|
||||||
LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
|
LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
|
||||||
for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
|
for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
|
||||||
the code between ENTER_PYTHON(tstate) and LEAVE_PYTHON.
|
the code between ENTER_PYTHON and LEAVE_PYTHON.
|
||||||
|
|
||||||
These locks expand to several statements and brackets; they should not be
|
These locks expand to several statements and brackets; they should not be
|
||||||
used in branches of if statements and the like.
|
used in branches of if statements and the like.
|
||||||
|
@ -172,24 +172,28 @@ PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static type_lock tcl_lock = 0;
|
static type_lock tcl_lock = 0;
|
||||||
|
static PyThreadState *tcl_tstate = NULL;
|
||||||
|
|
||||||
#define ENTER_TCL \
|
#define ENTER_TCL \
|
||||||
Py_BEGIN_ALLOW_THREADS acquire_lock(tcl_lock, 1);
|
{ PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
|
||||||
|
acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
|
||||||
|
|
||||||
#define LEAVE_TCL \
|
#define LEAVE_TCL \
|
||||||
release_lock(tcl_lock); Py_END_ALLOW_THREADS
|
tcl_tstate = NULL; release_lock(tcl_lock); Py_END_ALLOW_THREADS}
|
||||||
|
|
||||||
#define ENTER_OVERLAP \
|
#define ENTER_OVERLAP \
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
#define LEAVE_OVERLAP_TCL \
|
#define LEAVE_OVERLAP_TCL \
|
||||||
release_lock(tcl_lock);
|
tcl_tstate = NULL; release_lock(tcl_lock); }
|
||||||
|
|
||||||
#define ENTER_PYTHON(tstate) \
|
#define ENTER_PYTHON \
|
||||||
release_lock(tcl_lock); PyEval_RestoreThread((tstate));
|
{ PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
|
||||||
|
release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
|
||||||
|
|
||||||
#define LEAVE_PYTHON \
|
#define LEAVE_PYTHON \
|
||||||
PyEval_SaveThread(); acquire_lock(tcl_lock, 1);
|
{ PyThreadState *tstate = PyEval_SaveThread(); \
|
||||||
|
acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -197,7 +201,7 @@ static type_lock tcl_lock = 0;
|
||||||
#define LEAVE_TCL
|
#define LEAVE_TCL
|
||||||
#define ENTER_OVERLAP
|
#define ENTER_OVERLAP
|
||||||
#define LEAVE_OVERLAP_TCL
|
#define LEAVE_OVERLAP_TCL
|
||||||
#define ENTER_PYTHON(tstate)
|
#define ENTER_PYTHON
|
||||||
#define LEAVE_PYTHON
|
#define LEAVE_PYTHON
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1160,7 +1164,6 @@ Tkapp_Merge(self, args)
|
||||||
|
|
||||||
/* Client data struct */
|
/* Client data struct */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyThreadState *tstate;
|
|
||||||
PyObject *self;
|
PyObject *self;
|
||||||
PyObject *func;
|
PyObject *func;
|
||||||
} PythonCmd_ClientData;
|
} PythonCmd_ClientData;
|
||||||
|
@ -1189,8 +1192,7 @@ PythonCmd(clientData, interp, argc, argv)
|
||||||
PyObject *self, *func, *arg, *res, *tmp;
|
PyObject *self, *func, *arg, *res, *tmp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* XXX Should create fresh thread state? */
|
ENTER_PYTHON
|
||||||
ENTER_PYTHON(data->tstate)
|
|
||||||
|
|
||||||
/* TBD: no error checking here since we know, via the
|
/* TBD: no error checking here since we know, via the
|
||||||
* Tkapp_CreateCommand() that the client data is a two-tuple
|
* Tkapp_CreateCommand() that the client data is a two-tuple
|
||||||
|
@ -1235,7 +1237,7 @@ PythonCmdDelete(clientData)
|
||||||
{
|
{
|
||||||
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
|
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
|
||||||
|
|
||||||
ENTER_PYTHON(data->tstate)
|
ENTER_PYTHON
|
||||||
Py_XDECREF(data->self);
|
Py_XDECREF(data->self);
|
||||||
Py_XDECREF(data->func);
|
Py_XDECREF(data->func);
|
||||||
PyMem_DEL(data);
|
PyMem_DEL(data);
|
||||||
|
@ -1264,7 +1266,6 @@ Tkapp_CreateCommand(self, args)
|
||||||
data = PyMem_NEW(PythonCmd_ClientData, 1);
|
data = PyMem_NEW(PythonCmd_ClientData, 1);
|
||||||
if (!data)
|
if (!data)
|
||||||
return NULL;
|
return NULL;
|
||||||
data->tstate = PyThreadState_Get();
|
|
||||||
Py_XINCREF(self);
|
Py_XINCREF(self);
|
||||||
Py_XINCREF(func);
|
Py_XINCREF(func);
|
||||||
data->self = self;
|
data->self = self;
|
||||||
|
@ -1313,7 +1314,6 @@ Tkapp_DeleteCommand(self, args)
|
||||||
/** File Handler **/
|
/** File Handler **/
|
||||||
|
|
||||||
typedef struct _fhcdata {
|
typedef struct _fhcdata {
|
||||||
PyThreadState *tstate;
|
|
||||||
PyObject *func;
|
PyObject *func;
|
||||||
PyObject *file;
|
PyObject *file;
|
||||||
int id;
|
int id;
|
||||||
|
@ -1333,7 +1333,6 @@ NewFHCD(func, file, id)
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
Py_XINCREF(func);
|
Py_XINCREF(func);
|
||||||
Py_XINCREF(file);
|
Py_XINCREF(file);
|
||||||
p->tstate = PyThreadState_Get();
|
|
||||||
p->func = func;
|
p->func = func;
|
||||||
p->file = file;
|
p->file = file;
|
||||||
p->id = id;
|
p->id = id;
|
||||||
|
@ -1370,8 +1369,7 @@ FileHandler(clientData, mask)
|
||||||
FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
|
FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
|
||||||
PyObject *func, *file, *arg, *res;
|
PyObject *func, *file, *arg, *res;
|
||||||
|
|
||||||
/* XXX Should create fresh thread state? */
|
ENTER_PYTHON
|
||||||
ENTER_PYTHON(data->tstate)
|
|
||||||
func = data->func;
|
func = data->func;
|
||||||
file = data->file;
|
file = data->file;
|
||||||
|
|
||||||
|
@ -1500,7 +1498,6 @@ typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
Tcl_TimerToken token;
|
Tcl_TimerToken token;
|
||||||
PyObject *func;
|
PyObject *func;
|
||||||
PyThreadState *tstate;
|
|
||||||
} TkttObject;
|
} TkttObject;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1545,7 +1542,6 @@ Tktt_New(func)
|
||||||
Py_INCREF(func);
|
Py_INCREF(func);
|
||||||
v->token = NULL;
|
v->token = NULL;
|
||||||
v->func = func;
|
v->func = func;
|
||||||
v->tstate = PyThreadState_Get();
|
|
||||||
|
|
||||||
/* Extra reference, deleted when called or when handler is deleted */
|
/* Extra reference, deleted when called or when handler is deleted */
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
|
@ -1620,7 +1616,7 @@ TimerHandler(clientData)
|
||||||
|
|
||||||
v->func = NULL;
|
v->func = NULL;
|
||||||
|
|
||||||
ENTER_PYTHON(v->tstate)
|
ENTER_PYTHON
|
||||||
|
|
||||||
res = PyEval_CallObject(func, NULL);
|
res = PyEval_CallObject(func, NULL);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
|
@ -1667,6 +1663,9 @@ Tkapp_MainLoop(self, args)
|
||||||
PyObject *args;
|
PyObject *args;
|
||||||
{
|
{
|
||||||
int threshold = 0;
|
int threshold = 0;
|
||||||
|
#ifdef WITH_THREAD
|
||||||
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|i", &threshold))
|
if (!PyArg_ParseTuple(args, "|i", &threshold))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1681,7 +1680,9 @@ Tkapp_MainLoop(self, args)
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
acquire_lock(tcl_lock, 1);
|
acquire_lock(tcl_lock, 1);
|
||||||
|
tcl_tstate = tstate;
|
||||||
result = Tcl_DoOneEvent(TCL_DONT_WAIT);
|
result = Tcl_DoOneEvent(TCL_DONT_WAIT);
|
||||||
|
tcl_tstate = NULL;
|
||||||
release_lock(tcl_lock);
|
release_lock(tcl_lock);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
Sleep(20);
|
Sleep(20);
|
||||||
|
@ -1898,6 +1899,9 @@ static PyThreadState *event_tstate = NULL;
|
||||||
static int
|
static int
|
||||||
EventHook()
|
EventHook()
|
||||||
{
|
{
|
||||||
|
#if defined(WITH_THREAD) || defined(MS_WINDOWS)
|
||||||
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
|
#endif
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
FHANDLE tfile;
|
FHANDLE tfile;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1919,7 +1923,11 @@ EventHook()
|
||||||
#if defined(WITH_THREAD) || defined(MS_WINDOWS)
|
#if defined(WITH_THREAD) || defined(MS_WINDOWS)
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
acquire_lock(tcl_lock, 1);
|
acquire_lock(tcl_lock, 1);
|
||||||
|
tcl_tstate = tstate;
|
||||||
|
|
||||||
result = Tcl_DoOneEvent(TCL_DONT_WAIT);
|
result = Tcl_DoOneEvent(TCL_DONT_WAIT);
|
||||||
|
|
||||||
|
tcl_tstate = NULL;
|
||||||
release_lock(tcl_lock);
|
release_lock(tcl_lock);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
Sleep(20);
|
Sleep(20);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue