@@ -35,14 +35,13 @@ PERFORMANCE OF THIS SOFTWARE.
35
35
#include "Python.h"
36
36
37
37
#ifndef WITH_THREAD
38
- Error ! The rest of Python is not compiled with thread support .
39
- Rerun configure , adding a -- with - thread option .
38
+ #error "Error! The rest of Python is not compiled with thread support."
39
+ #error "Rerun configure, adding a --with-thread option."
40
+ #error "Then run `make clean' followed by `make'."
40
41
#endif
41
42
42
43
#include "thread.h"
43
44
44
- extern int _PyThread_Started ;
45
-
46
45
static PyObject * ThreadError ;
47
46
48
47
@@ -192,52 +191,90 @@ static PyTypeObject Locktype = {
192
191
193
192
/* Module functions */
194
193
194
+ struct bootstate {
195
+ PyInterpreterState * interp ;
196
+ PyObject * func ;
197
+ PyObject * args ;
198
+ PyObject * keyw ;
199
+ };
200
+
195
201
static void
196
- t_bootstrap (args_raw )
197
- void * args_raw ;
202
+ t_bootstrap (boot_raw )
203
+ void * boot_raw ;
198
204
{
199
- PyObject * args = (PyObject * ) args_raw ;
200
- PyObject * func , * arg , * res ;
201
-
202
- _PyThread_Started ++ ;
205
+ struct bootstate * boot = (struct bootstate * ) boot_raw ;
206
+ PyThreadState * alttstate , * tstate ;
207
+ PyObject * res ;
203
208
209
+ tstate = PyThreadState_New (boot -> interp );
204
210
PyEval_RestoreThread ((void * )NULL );
205
- func = PyTuple_GetItem (args , 0 );
206
- arg = PyTuple_GetItem (args , 1 );
207
- res = PyEval_CallObject (func , arg );
208
- Py_DECREF (args ); /* Matches the INCREF(args) in thread_start_new_thread */
211
+ alttstate = PyThreadState_Swap (tstate );
212
+ res = PyEval_CallObjectWithKeywords (
213
+ boot -> func , boot -> args , boot -> keyw );
214
+ Py_DECREF (boot -> func );
215
+ Py_DECREF (boot -> args );
216
+ Py_XDECREF (boot -> keyw );
217
+ PyMem_DEL (boot_raw );
209
218
if (res == NULL ) {
210
219
if (PyErr_Occurred () == PyExc_SystemExit )
211
220
PyErr_Clear ();
212
221
else {
213
222
fprintf (stderr , "Unhandled exception in thread:\n" );
214
- PyErr_Print (); /* From pythonmain.c */
223
+ PyErr_Print ();
215
224
}
216
225
}
217
226
else
218
227
Py_DECREF (res );
219
- (void ) PyEval_SaveThread (); /* Should always be NULL */
228
+ (void ) PyThreadState_Swap (alttstate );
229
+ (void ) PyEval_SaveThread ();
230
+ PyThreadState_Delete (tstate );
220
231
exit_thread ();
221
232
}
222
233
223
234
static PyObject *
224
- thread_start_new_thread (self , args )
235
+ thread_start_new_thread (self , fargs )
225
236
PyObject * self ; /* Not used */
226
- PyObject * args ;
237
+ PyObject * fargs ;
227
238
{
228
- PyObject * func , * arg ;
239
+ PyObject * func , * args = NULL , * keyw = NULL ;
240
+ struct bootstate * boot ;
229
241
230
- if (!PyArg_Parse (args , "(OO)" , & func , & arg ))
242
+ if (!PyArg_ParseTuple (fargs , "OO|O" , & func , & args , & keyw ))
243
+ return NULL ;
244
+ if (!PyCallable_Check (func )) {
245
+ PyErr_SetString (PyExc_TypeError ,
246
+ "first arg must be callable" );
231
247
return NULL ;
248
+ }
249
+ if (!PyTuple_Check (args )) {
250
+ PyErr_SetString (PyExc_TypeError ,
251
+ "optional 2nd arg must be a tuple" );
252
+ return NULL ;
253
+ }
254
+ if (keyw != NULL && !PyDict_Check (keyw )) {
255
+ PyErr_SetString (PyExc_TypeError ,
256
+ "optional 3rd arg must be a dictionary" );
257
+ return NULL ;
258
+ }
259
+ boot = PyMem_NEW (struct bootstate , 1 );
260
+ if (boot == NULL )
261
+ return PyErr_NoMemory ();
262
+ boot -> interp = PyThreadState_Get ()-> interpreter_state ;
263
+ boot -> func = func ;
264
+ boot -> args = args ;
265
+ boot -> keyw = keyw ;
266
+ Py_INCREF (func );
232
267
Py_INCREF (args );
233
- /* Initialize the interpreter's stack save/restore mechanism */
234
- PyEval_InitThreads ();
235
- if (!start_new_thread (t_bootstrap , (void * ) args )) {
236
- Py_DECREF (args );
268
+ Py_XINCREF (keyw );
269
+ PyEval_InitThreads (); /* Start the interpreter's thread-awareness */
270
+ if (!start_new_thread (t_bootstrap , (void * ) boot )) {
237
271
PyErr_SetString (ThreadError , "can't start new thread\n" );
272
+ Py_DECREF (func );
273
+ Py_DECREF (args );
274
+ Py_XDECREF (keyw );
275
+ PyMem_DEL (boot );
238
276
return NULL ;
239
277
}
240
- /* Otherwise the DECREF(args) is done by t_bootstrap */
241
278
Py_INCREF (Py_None );
242
279
return Py_None ;
243
280
}
@@ -294,8 +331,8 @@ thread_get_ident(self, args)
294
331
}
295
332
296
333
static PyMethodDef thread_methods [] = {
297
- {"start_new_thread" , (PyCFunction )thread_start_new_thread },
298
- {"start_new" , (PyCFunction )thread_start_new_thread },
334
+ {"start_new_thread" , (PyCFunction )thread_start_new_thread , 1 },
335
+ {"start_new" , (PyCFunction )thread_start_new_thread , 1 },
299
336
{"allocate_lock" , (PyCFunction )thread_allocate_lock },
300
337
{"allocate" , (PyCFunction )thread_allocate_lock },
301
338
{"exit_thread" , (PyCFunction )thread_exit_thread },
0 commit comments