[proxy] github.com← back | site home | direct (HTTPS) ↗ | proxy home | ◑ dark◐ light

Massive changes for separate thread state management. · python/cpython@a027efa

@@ -35,14 +35,13 @@ PERFORMANCE OF THIS SOFTWARE.

3535

#include "Python.h"

36363737

#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'."

4041

#endif

41424243

#include "thread.h"

434444-

extern int _PyThread_Started;

45-4645

static PyObject *ThreadError;

47464847

@@ -192,52 +191,90 @@ static PyTypeObject Locktype = {

192191193192

/* Module functions */

194193194+

struct bootstate {

195+

PyInterpreterState *interp;

196+

PyObject *func;

197+

PyObject *args;

198+

PyObject *keyw;

199+

};

200+195201

static void

196-

t_bootstrap(args_raw)

197-

void *args_raw;

202+

t_bootstrap(boot_raw)

203+

void *boot_raw;

198204

{

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;

203208209+

tstate = PyThreadState_New(boot->interp);

204210

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

209218

if (res == NULL) {

210219

if (PyErr_Occurred() == PyExc_SystemExit)

211220

PyErr_Clear();

212221

else {

213222

fprintf(stderr, "Unhandled exception in thread:\n");

214-

PyErr_Print(); /* From pythonmain.c */

223+

PyErr_Print();

215224

}

216225

}

217226

else

218227

Py_DECREF(res);

219-

(void) PyEval_SaveThread(); /* Should always be NULL */

228+

(void) PyThreadState_Swap(alttstate);

229+

(void) PyEval_SaveThread();

230+

PyThreadState_Delete(tstate);

220231

exit_thread();

221232

}

222233223234

static PyObject *

224-

thread_start_new_thread(self, args)

235+

thread_start_new_thread(self, fargs)

225236

PyObject *self; /* Not used */

226-

PyObject *args;

237+

PyObject *fargs;

227238

{

228-

PyObject *func, *arg;

239+

PyObject *func, *args = NULL, *keyw = NULL;

240+

struct bootstate *boot;

229241230-

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

231247

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

232267

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)) {

237271

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

238276

return NULL;

239277

}

240-

/* Otherwise the DECREF(args) is done by t_bootstrap */

241278

Py_INCREF(Py_None);

242279

return Py_None;

243280

}

@@ -294,8 +331,8 @@ thread_get_ident(self, args)

294331

}

295332296333

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},

299336

{"allocate_lock", (PyCFunction)thread_allocate_lock},

300337

{"allocate", (PyCFunction)thread_allocate_lock},

301338

{"exit_thread", (PyCFunction)thread_exit_thread},