@@ -125,52 +125,60 @@ Copyright (C) 1994 Steen Lumholt.
125125
126126/* The threading situation is complicated. Tcl is not thread-safe, except
127127 when configured with --enable-threads.
128- So we need to use a lock around all uses of Tcl. Previously, the Python
129- interpreter lock was used for this. However, this causes problems when
130- other Python threads need to run while Tcl is blocked waiting for events.
131-
132- To solve this problem, a separate lock for Tcl is introduced. Holding it
133- is incompatible with holding Python's interpreter lock. The following four
134- macros manipulate both locks together.
135-
136- ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
137- Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
138- that could call an event handler, or otherwise affect the state of a Tcl
139- interpreter. These assume that the surrounding code has the Python
140- interpreter lock; inside the brackets, the Python interpreter lock has been
141- released and the lock for Tcl has been acquired.
142-
143- Sometimes, it is necessary to have both the Python lock and the Tcl lock.
144- (For example, when transferring data from the Tcl interpreter result to a
145- Python string object.) This can be done by using different macros to close
146- the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
147- the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
148- releases the Tcl lock.
128+
129+ So we need to use a lock around all uses of Tcl. Previously, the
130+ Python interpreter lock was used for this. However, this causes
131+ problems when other Python threads need to run while Tcl is blocked
132+ waiting for events.
133+
134+ To solve this problem, a separate lock for Tcl is introduced.
135+ Holding it is incompatible with holding Python's interpreter lock.
136+ The following four macros manipulate both locks together.
137+
138+ ENTER_TCL and LEAVE_TCL are brackets, just like
139+ Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
140+ used whenever a call into Tcl is made that could call an event
141+ handler, or otherwise affect the state of a Tcl interpreter. These
142+ assume that the surrounding code has the Python interpreter lock;
143+ inside the brackets, the Python interpreter lock has been released
144+ and the lock for Tcl has been acquired.
145+
146+ Sometimes, it is necessary to have both the Python lock and the Tcl
147+ lock. (For example, when transferring data from the Tcl
148+ interpreter result to a Python string object.) This can be done by
149+ using different macros to close the ENTER_TCL block: ENTER_OVERLAP
150+ reacquires the Python lock (and restores the thread state) but
151+ doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
152+ lock.
149153
150154 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
151- handlers when the handler needs to use Python. Such event handlers are
152- entered while the lock for Tcl is held; the event handler presumably needs
153- to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
154- the Python interpreter lock, restoring the appropriate thread state, and
155- LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
156- for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
157- the code between ENTER_PYTHON and LEAVE_PYTHON.
158-
159- These locks expand to several statements and brackets; they should not be
160- used in branches of if statements and the like.
161-
162- If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
163- only valid in the thread that created it, and all Tk activity must happen in this
164- thread, also. That means that the mainloop must be invoked in the thread that
165- created the interpreter. Invoking commands from other threads is possible;
166- _tkinter will queue an event for the interpreter thread, which will then
167- execute the command and pass back the result. If the main thread is not in the
168- mainloop, and invoking commands causes an exception; if the main loop is running
169- but not processing events, the command invocation will block.
170-
171- In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
172- anymore, since multiple Tcl interpreters may simultaneously dispatch in different
173- threads. So we use the Tcl TLS API.
155+ handlers when the handler needs to use Python. Such event handlers
156+ are entered while the lock for Tcl is held; the event handler
157+ presumably needs to use Python. ENTER_PYTHON releases the lock for
158+ Tcl and acquires the Python interpreter lock, restoring the
159+ appropriate thread state, and LEAVE_PYTHON releases the Python
160+ interpreter lock and re-acquires the lock for Tcl. It is okay for
161+ ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
162+ ENTER_PYTHON and LEAVE_PYTHON.
163+
164+ These locks expand to several statements and brackets; they should
165+ not be used in branches of if statements and the like.
166+
167+ If Tcl is threaded, this approach won't work anymore. The Tcl
168+ interpreter is only valid in the thread that created it, and all Tk
169+ activity must happen in this thread, also. That means that the
170+ mainloop must be invoked in the thread that created the
171+ interpreter. Invoking commands from other threads is possible;
172+ _tkinter will queue an event for the interpreter thread, which will
173+ then execute the command and pass back the result. If the main
174+ thread is not in the mainloop, and invoking commands causes an
175+ exception; if the main loop is running but not processing events,
176+ the command invocation will block.
177+
178+ In addition, for a threaded Tcl, a single global tcl_tstate won't
179+ be sufficient anymore, since multiple Tcl interpreters may
180+ simultaneously dispatch in different threads. So we use the Tcl TLS
181+ API.
174182
175183*/
176184
@@ -179,7 +187,8 @@ static PyThread_type_lock tcl_lock = 0;
179187#ifdef TCL_THREADS
180188static Tcl_ThreadDataKey state_key ;
181189typedef PyThreadState * ThreadSpecificData ;
182- #define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
190+ #define tcl_tstate \
191+ (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
183192#else
184193static PyThreadState * tcl_tstate = NULL ;
185194#endif
@@ -189,7 +198,8 @@ static PyThreadState *tcl_tstate = NULL;
189198 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
190199
191200#define LEAVE_TCL \
192- tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
201+ tcl_tstate = NULL; \
202+ if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
193203
194204#define ENTER_OVERLAP \
195205 Py_END_ALLOW_THREADS
@@ -199,7 +209,8 @@ static PyThreadState *tcl_tstate = NULL;
199209
200210#define ENTER_PYTHON \
201211 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
202- if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
212+ if(tcl_lock) \
213+ PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
203214
204215#define LEAVE_PYTHON \
205216 { PyThreadState *tstate = PyEval_SaveThread(); \
@@ -208,7 +219,8 @@ static PyThreadState *tcl_tstate = NULL;
208219#define CHECK_TCL_APPARTMENT \
209220 if (((TkappObject *)self)->threaded && \
210221 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
211- PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
222+ PyErr_SetString(PyExc_RuntimeError, \
223+ "Calling Tcl from different appartment"); \
212224 return 0; \
213225 }
214226
@@ -367,9 +379,9 @@ Split(char *list)
367379 return v ;
368380}
369381
370- /* In some cases, Tcl will still return strings that are supposed to be
371- lists. SplitObj walks through a nested tuple, finding string objects that
372- need to be split. */
382+ /* In some cases, Tcl will still return strings that are supposed to
383+ be lists. SplitObj walks through a nested tuple, finding string
384+ objects that need to be split. */
373385
374386static PyObject *
375387SplitObj (PyObject * arg )
@@ -499,7 +511,8 @@ Tkapp_New(char *screenName, char *className,
499511
500512#ifndef TCL_THREADS
501513 if (v -> threaded ) {
502- PyErr_SetString (PyExc_RuntimeError , "Tcl is threaded but _tkinter is not" );
514+ PyErr_SetString (PyExc_RuntimeError ,
515+ "Tcl is threaded but _tkinter is not" );
503516 Py_DECREF (v );
504517 return 0 ;
505518 }
@@ -1479,7 +1492,8 @@ GetVar(PyObject *self, PyObject *args, int flags)
14791492 tres = Tcl_GetVar2Ex (Tkapp_Interp (self ), name1 , name2 , flags );
14801493 ENTER_OVERLAP
14811494 if (tres == NULL) {
1482- PyErr_SetString (Tkinter_TclError , Tcl_GetStringResult (Tkapp_Interp (self )));
1495+ PyErr_SetString (Tkinter_TclError ,
1496+ Tcl_GetStringResult (Tkapp_Interp (self )));
14831497 } else {
14841498 if (((TkappObject * )self )-> wantobjects ) {
14851499 res = FromObj (self , tres );
@@ -1538,7 +1552,8 @@ Tkapp_UnsetVar(PyObject *self, PyObject *args)
15381552static PyObject *
15391553Tkapp_GlobalUnsetVar (PyObject * self , PyObject * args )
15401554{
1541- return var_invoke (UnsetVar , self , args , TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY );
1555+ return var_invoke (UnsetVar , self , args ,
1556+ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY );
15421557}
15431558
15441559
@@ -2407,7 +2422,8 @@ Tkapp_TkInit(PyObject *self, PyObject *args)
24072422 }
24082423 if (_tk_exists == NULL || strcmp (_tk_exists , "1" ) != 0 ) {
24092424 if (Tk_Init (interp ) == TCL_ERROR ) {
2410- PyErr_SetString (Tkinter_TclError , Tcl_GetStringResult (Tkapp_Interp (self )));
2425+ PyErr_SetString (Tkinter_TclError ,
2426+ Tcl_GetStringResult (Tkapp_Interp (self )));
24112427#ifdef TKINTER_PROTECT_LOADTK
24122428 tk_load_failed = 1 ;
24132429#endif
@@ -2649,7 +2665,7 @@ Tkinter_Create(PyObject *self, PyObject *args)
26492665 return NULL ;
26502666
26512667 return (PyObject * ) Tkapp_New (screenName , className ,
2652- interactive , wantobjects , wantTk ,
2668+ interactive , wantobjects , wantTk ,
26532669 sync , use );
26542670}
26552671
0 commit comments