diff options
Diffstat (limited to 'Modules/_threadmodule.c')
-rw-r--r-- | Modules/_threadmodule.c | 942 |
1 files changed, 471 insertions, 471 deletions
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 3d4578a..e218ed6 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -18,36 +18,36 @@ static PyObject *ThreadError; /* Lock objects */ typedef struct { - PyObject_HEAD - PyThread_type_lock lock_lock; + PyObject_HEAD + PyThread_type_lock lock_lock; } lockobject; static void lock_dealloc(lockobject *self) { - if (self->lock_lock != NULL) { - /* Unlock the lock so it's safe to free it */ - PyThread_acquire_lock(self->lock_lock, 0); - PyThread_release_lock(self->lock_lock); - - PyThread_free_lock(self->lock_lock); - } - PyObject_Del(self); + if (self->lock_lock != NULL) { + /* Unlock the lock so it's safe to free it */ + PyThread_acquire_lock(self->lock_lock, 0); + PyThread_release_lock(self->lock_lock); + + PyThread_free_lock(self->lock_lock); + } + PyObject_Del(self); } static PyObject * lock_PyThread_acquire_lock(lockobject *self, PyObject *args) { - int i = 1; + int i = 1; - if (!PyArg_ParseTuple(args, "|i:acquire", &i)) - return NULL; + if (!PyArg_ParseTuple(args, "|i:acquire", &i)) + return NULL; - Py_BEGIN_ALLOW_THREADS - i = PyThread_acquire_lock(self->lock_lock, i); - Py_END_ALLOW_THREADS + Py_BEGIN_ALLOW_THREADS + i = PyThread_acquire_lock(self->lock_lock, i); + Py_END_ALLOW_THREADS - return PyBool_FromLong((long)i); + return PyBool_FromLong((long)i); } PyDoc_STRVAR(acquire_doc, @@ -64,16 +64,16 @@ The blocking operation is not interruptible."); static PyObject * lock_PyThread_release_lock(lockobject *self) { - /* Sanity check: the lock must be locked */ - if (PyThread_acquire_lock(self->lock_lock, 0)) { - PyThread_release_lock(self->lock_lock); - PyErr_SetString(ThreadError, "release unlocked lock"); - return NULL; - } - - PyThread_release_lock(self->lock_lock); - Py_INCREF(Py_None); - return Py_None; + /* Sanity check: the lock must be locked */ + if (PyThread_acquire_lock(self->lock_lock, 0)) { + PyThread_release_lock(self->lock_lock); + PyErr_SetString(ThreadError, "release unlocked lock"); + return NULL; + } + + PyThread_release_lock(self->lock_lock); + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(release_doc, @@ -87,11 +87,11 @@ but it needn't be locked by the same thread that unlocks it."); static PyObject * lock_locked_lock(lockobject *self) { - if (PyThread_acquire_lock(self->lock_lock, 0)) { - PyThread_release_lock(self->lock_lock); - return PyBool_FromLong(0L); - } - return PyBool_FromLong(1L); + if (PyThread_acquire_lock(self->lock_lock, 0)) { + PyThread_release_lock(self->lock_lock); + return PyBool_FromLong(0L); + } + return PyBool_FromLong(1L); } PyDoc_STRVAR(locked_doc, @@ -101,71 +101,71 @@ PyDoc_STRVAR(locked_doc, Return whether the lock is in the locked state."); static PyMethodDef lock_methods[] = { - {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, - METH_VARARGS, acquire_doc}, - {"acquire", (PyCFunction)lock_PyThread_acquire_lock, - METH_VARARGS, acquire_doc}, - {"release_lock", (PyCFunction)lock_PyThread_release_lock, - METH_NOARGS, release_doc}, - {"release", (PyCFunction)lock_PyThread_release_lock, - METH_NOARGS, release_doc}, - {"locked_lock", (PyCFunction)lock_locked_lock, - METH_NOARGS, locked_doc}, - {"locked", (PyCFunction)lock_locked_lock, - METH_NOARGS, locked_doc}, - {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, - METH_VARARGS, acquire_doc}, - {"__exit__", (PyCFunction)lock_PyThread_release_lock, - METH_VARARGS, release_doc}, - {NULL, NULL} /* sentinel */ + {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, + METH_VARARGS, acquire_doc}, + {"acquire", (PyCFunction)lock_PyThread_acquire_lock, + METH_VARARGS, acquire_doc}, + {"release_lock", (PyCFunction)lock_PyThread_release_lock, + METH_NOARGS, release_doc}, + {"release", (PyCFunction)lock_PyThread_release_lock, + METH_NOARGS, release_doc}, + {"locked_lock", (PyCFunction)lock_locked_lock, + METH_NOARGS, locked_doc}, + {"locked", (PyCFunction)lock_locked_lock, + METH_NOARGS, locked_doc}, + {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, + METH_VARARGS, acquire_doc}, + {"__exit__", (PyCFunction)lock_PyThread_release_lock, + METH_VARARGS, release_doc}, + {NULL, NULL} /* sentinel */ }; static PyTypeObject Locktype = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "_thread.lock", /*tp_name*/ - sizeof(lockobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)lock_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - lock_methods, /*tp_methods*/ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "_thread.lock", /*tp_name*/ + sizeof(lockobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)lock_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_reserved*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + lock_methods, /*tp_methods*/ }; static lockobject * newlockobject(void) { - lockobject *self; - self = PyObject_New(lockobject, &Locktype); - if (self == NULL) - return NULL; - self->lock_lock = PyThread_allocate_lock(); - if (self->lock_lock == NULL) { - Py_DECREF(self); - PyErr_SetString(ThreadError, "can't allocate lock"); - return NULL; - } - return self; + lockobject *self; + self = PyObject_New(lockobject, &Locktype); + if (self == NULL) + return NULL; + self->lock_lock = PyThread_allocate_lock(); + if (self->lock_lock == NULL) { + Py_DECREF(self); + PyErr_SetString(ThreadError, "can't allocate lock"); + return NULL; + } + return self; } /* Thread-local objects */ @@ -173,351 +173,351 @@ newlockobject(void) #include "structmember.h" typedef struct { - PyObject_HEAD - PyObject *key; - PyObject *args; - PyObject *kw; - PyObject *dict; + PyObject_HEAD + PyObject *key; + PyObject *args; + PyObject *kw; + PyObject *dict; } localobject; static PyObject * local_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - localobject *self; - PyObject *tdict; - - if (type->tp_init == PyBaseObject_Type.tp_init - && ((args && PyObject_IsTrue(args)) - || (kw && PyObject_IsTrue(kw)))) { - PyErr_SetString(PyExc_TypeError, - "Initialization arguments are not supported"); - return NULL; - } - - self = (localobject *)type->tp_alloc(type, 0); - if (self == NULL) - return NULL; - - Py_XINCREF(args); - self->args = args; - Py_XINCREF(kw); - self->kw = kw; - self->dict = NULL; /* making sure */ - self->key = PyUnicode_FromFormat("thread.local.%p", self); - if (self->key == NULL) - goto err; - - self->dict = PyDict_New(); - if (self->dict == NULL) - goto err; - - tdict = PyThreadState_GetDict(); - if (tdict == NULL) { - PyErr_SetString(PyExc_SystemError, - "Couldn't get thread-state dictionary"); - goto err; - } - - if (PyDict_SetItem(tdict, self->key, self->dict) < 0) - goto err; - - return (PyObject *)self; + localobject *self; + PyObject *tdict; + + if (type->tp_init == PyBaseObject_Type.tp_init + && ((args && PyObject_IsTrue(args)) + || (kw && PyObject_IsTrue(kw)))) { + PyErr_SetString(PyExc_TypeError, + "Initialization arguments are not supported"); + return NULL; + } + + self = (localobject *)type->tp_alloc(type, 0); + if (self == NULL) + return NULL; + + Py_XINCREF(args); + self->args = args; + Py_XINCREF(kw); + self->kw = kw; + self->dict = NULL; /* making sure */ + self->key = PyUnicode_FromFormat("thread.local.%p", self); + if (self->key == NULL) + goto err; + + self->dict = PyDict_New(); + if (self->dict == NULL) + goto err; + + tdict = PyThreadState_GetDict(); + if (tdict == NULL) { + PyErr_SetString(PyExc_SystemError, + "Couldn't get thread-state dictionary"); + goto err; + } + + if (PyDict_SetItem(tdict, self->key, self->dict) < 0) + goto err; + + return (PyObject *)self; err: - Py_DECREF(self); - return NULL; + Py_DECREF(self); + return NULL; } static int local_traverse(localobject *self, visitproc visit, void *arg) { - Py_VISIT(self->args); - Py_VISIT(self->kw); - Py_VISIT(self->dict); - return 0; + Py_VISIT(self->args); + Py_VISIT(self->kw); + Py_VISIT(self->dict); + return 0; } static int local_clear(localobject *self) { - Py_CLEAR(self->args); - Py_CLEAR(self->kw); - Py_CLEAR(self->dict); - return 0; + Py_CLEAR(self->args); + Py_CLEAR(self->kw); + Py_CLEAR(self->dict); + return 0; } static void local_dealloc(localobject *self) { - PyThreadState *tstate; - if (self->key - && (tstate = PyThreadState_Get()) - && tstate->interp) { - for(tstate = PyInterpreterState_ThreadHead(tstate->interp); - tstate; - tstate = PyThreadState_Next(tstate)) - if (tstate->dict && - PyDict_GetItem(tstate->dict, self->key)) - PyDict_DelItem(tstate->dict, self->key); - } - - Py_XDECREF(self->key); - local_clear(self); - Py_TYPE(self)->tp_free((PyObject*)self); + PyThreadState *tstate; + if (self->key + && (tstate = PyThreadState_Get()) + && tstate->interp) { + for(tstate = PyInterpreterState_ThreadHead(tstate->interp); + tstate; + tstate = PyThreadState_Next(tstate)) + if (tstate->dict && + PyDict_GetItem(tstate->dict, self->key)) + PyDict_DelItem(tstate->dict, self->key); + } + + Py_XDECREF(self->key); + local_clear(self); + Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject * _ldict(localobject *self) { - PyObject *tdict, *ldict; - - tdict = PyThreadState_GetDict(); - if (tdict == NULL) { - PyErr_SetString(PyExc_SystemError, - "Couldn't get thread-state dictionary"); - return NULL; - } - - ldict = PyDict_GetItem(tdict, self->key); - if (ldict == NULL) { - ldict = PyDict_New(); /* we own ldict */ - - if (ldict == NULL) - return NULL; - else { - int i = PyDict_SetItem(tdict, self->key, ldict); - Py_DECREF(ldict); /* now ldict is borrowed */ - if (i < 0) - return NULL; - } - - Py_CLEAR(self->dict); - Py_INCREF(ldict); - self->dict = ldict; /* still borrowed */ - - if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && - Py_TYPE(self)->tp_init((PyObject*)self, - self->args, self->kw) < 0) { - /* we need to get rid of ldict from thread so - we create a new one the next time we do an attr - acces */ - PyDict_DelItem(tdict, self->key); - return NULL; - } - - } - - /* The call to tp_init above may have caused another thread to run. - Install our ldict again. */ - if (self->dict != ldict) { - Py_CLEAR(self->dict); - Py_INCREF(ldict); - self->dict = ldict; - } - - return ldict; + PyObject *tdict, *ldict; + + tdict = PyThreadState_GetDict(); + if (tdict == NULL) { + PyErr_SetString(PyExc_SystemError, + "Couldn't get thread-state dictionary"); + return NULL; + } + + ldict = PyDict_GetItem(tdict, self->key); + if (ldict == NULL) { + ldict = PyDict_New(); /* we own ldict */ + + if (ldict == NULL) + return NULL; + else { + int i = PyDict_SetItem(tdict, self->key, ldict); + Py_DECREF(ldict); /* now ldict is borrowed */ + if (i < 0) + return NULL; + } + + Py_CLEAR(self->dict); + Py_INCREF(ldict); + self->dict = ldict; /* still borrowed */ + + if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && + Py_TYPE(self)->tp_init((PyObject*)self, + self->args, self->kw) < 0) { + /* we need to get rid of ldict from thread so + we create a new one the next time we do an attr + acces */ + PyDict_DelItem(tdict, self->key); + return NULL; + } + + } + + /* The call to tp_init above may have caused another thread to run. + Install our ldict again. */ + if (self->dict != ldict) { + Py_CLEAR(self->dict); + Py_INCREF(ldict); + self->dict = ldict; + } + + return ldict; } static int local_setattro(localobject *self, PyObject *name, PyObject *v) { - PyObject *ldict; - - ldict = _ldict(self); - if (ldict == NULL) - return -1; + PyObject *ldict; - return PyObject_GenericSetAttr((PyObject *)self, name, v); + ldict = _ldict(self); + if (ldict == NULL) + return -1; + + return PyObject_GenericSetAttr((PyObject *)self, name, v); } static PyObject * local_getdict(localobject *self, void *closure) { - if (self->dict == NULL) { - PyErr_SetString(PyExc_AttributeError, "__dict__"); - return NULL; - } + if (self->dict == NULL) { + PyErr_SetString(PyExc_AttributeError, "__dict__"); + return NULL; + } - Py_INCREF(self->dict); - return self->dict; + Py_INCREF(self->dict); + return self->dict; } static PyGetSetDef local_getset[] = { - {"__dict__", (getter)local_getdict, (setter)NULL, - "Local-data dictionary", NULL}, - {NULL} /* Sentinel */ + {"__dict__", (getter)local_getdict, (setter)NULL, + "Local-data dictionary", NULL}, + {NULL} /* Sentinel */ }; static PyObject *local_getattro(localobject *, PyObject *); static PyTypeObject localtype = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_thread._local", - /* tp_basicsize */ sizeof(localobject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)local_dealloc, - /* tp_print */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_reserved */ 0, - /* tp_repr */ 0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ (getattrofunc)local_getattro, - /* tp_setattro */ (setattrofunc)local_setattro, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - /* tp_doc */ "Thread-local data", - /* tp_traverse */ (traverseproc)local_traverse, - /* tp_clear */ (inquiry)local_clear, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ 0, - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ 0, - /* tp_members */ 0, - /* tp_getset */ local_getset, - /* tp_base */ 0, - /* tp_dict */ 0, /* internal use */ - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ offsetof(localobject, dict), - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ local_new, - /* tp_free */ 0, /* Low-level free-mem routine */ - /* tp_is_gc */ 0, /* For PyObject_IS_GC */ + PyVarObject_HEAD_INIT(NULL, 0) + /* tp_name */ "_thread._local", + /* tp_basicsize */ sizeof(localobject), + /* tp_itemsize */ 0, + /* tp_dealloc */ (destructor)local_dealloc, + /* tp_print */ 0, + /* tp_getattr */ 0, + /* tp_setattr */ 0, + /* tp_reserved */ 0, + /* tp_repr */ 0, + /* tp_as_number */ 0, + /* tp_as_sequence */ 0, + /* tp_as_mapping */ 0, + /* tp_hash */ 0, + /* tp_call */ 0, + /* tp_str */ 0, + /* tp_getattro */ (getattrofunc)local_getattro, + /* tp_setattro */ (setattrofunc)local_setattro, + /* tp_as_buffer */ 0, + /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + /* tp_doc */ "Thread-local data", + /* tp_traverse */ (traverseproc)local_traverse, + /* tp_clear */ (inquiry)local_clear, + /* tp_richcompare */ 0, + /* tp_weaklistoffset */ 0, + /* tp_iter */ 0, + /* tp_iternext */ 0, + /* tp_methods */ 0, + /* tp_members */ 0, + /* tp_getset */ local_getset, + /* tp_base */ 0, + /* tp_dict */ 0, /* internal use */ + /* tp_descr_get */ 0, + /* tp_descr_set */ 0, + /* tp_dictoffset */ offsetof(localobject, dict), + /* tp_init */ 0, + /* tp_alloc */ 0, + /* tp_new */ local_new, + /* tp_free */ 0, /* Low-level free-mem routine */ + /* tp_is_gc */ 0, /* For PyObject_IS_GC */ }; static PyObject * local_getattro(localobject *self, PyObject *name) { - PyObject *ldict, *value; + PyObject *ldict, *value; - ldict = _ldict(self); - if (ldict == NULL) - return NULL; + ldict = _ldict(self); + if (ldict == NULL) + return NULL; - if (Py_TYPE(self) != &localtype) - /* use generic lookup for subtypes */ - return PyObject_GenericGetAttr((PyObject *)self, name); + if (Py_TYPE(self) != &localtype) + /* use generic lookup for subtypes */ + return PyObject_GenericGetAttr((PyObject *)self, name); - /* Optimization: just look in dict ourselves */ - value = PyDict_GetItem(ldict, name); - if (value == NULL) - /* Fall back on generic to get __class__ and __dict__ */ - return PyObject_GenericGetAttr((PyObject *)self, name); + /* Optimization: just look in dict ourselves */ + value = PyDict_GetItem(ldict, name); + if (value == NULL) + /* Fall back on generic to get __class__ and __dict__ */ + return PyObject_GenericGetAttr((PyObject *)self, name); - Py_INCREF(value); - return value; + Py_INCREF(value); + return value; } /* Module functions */ struct bootstate { - PyInterpreterState *interp; - PyObject *func; - PyObject *args; - PyObject *keyw; - PyThreadState *tstate; + PyInterpreterState *interp; + PyObject *func; + PyObject *args; + PyObject *keyw; + PyThreadState *tstate; }; static void t_bootstrap(void *boot_raw) { - struct bootstate *boot = (struct bootstate *) boot_raw; - PyThreadState *tstate; - PyObject *res; - - tstate = boot->tstate; - tstate->thread_id = PyThread_get_thread_ident(); - _PyThreadState_Init(tstate); - PyEval_AcquireThread(tstate); - res = PyEval_CallObjectWithKeywords( - boot->func, boot->args, boot->keyw); - if (res == NULL) { - if (PyErr_ExceptionMatches(PyExc_SystemExit)) - PyErr_Clear(); - else { - PyObject *file; - PySys_WriteStderr( - "Unhandled exception in thread started by "); - file = PySys_GetObject("stderr"); - if (file != NULL && file != Py_None) - PyFile_WriteObject(boot->func, file, 0); - else - PyObject_Print(boot->func, stderr, 0); - PySys_WriteStderr("\n"); - PyErr_PrintEx(0); - } - } - else - Py_DECREF(res); - Py_DECREF(boot->func); - Py_DECREF(boot->args); - Py_XDECREF(boot->keyw); - PyMem_DEL(boot_raw); - PyThreadState_Clear(tstate); - PyThreadState_DeleteCurrent(); - PyThread_exit_thread(); + struct bootstate *boot = (struct bootstate *) boot_raw; + PyThreadState *tstate; + PyObject *res; + + tstate = boot->tstate; + tstate->thread_id = PyThread_get_thread_ident(); + _PyThreadState_Init(tstate); + PyEval_AcquireThread(tstate); + res = PyEval_CallObjectWithKeywords( + boot->func, boot->args, boot->keyw); + if (res == NULL) { + if (PyErr_ExceptionMatches(PyExc_SystemExit)) + PyErr_Clear(); + else { + PyObject *file; + PySys_WriteStderr( + "Unhandled exception in thread started by "); + file = PySys_GetObject("stderr"); + if (file != NULL && file != Py_None) + PyFile_WriteObject(boot->func, file, 0); + else + PyObject_Print(boot->func, stderr, 0); + PySys_WriteStderr("\n"); + PyErr_PrintEx(0); + } + } + else + Py_DECREF(res); + Py_DECREF(boot->func); + Py_DECREF(boot->args); + Py_XDECREF(boot->keyw); + PyMem_DEL(boot_raw); + PyThreadState_Clear(tstate); + PyThreadState_DeleteCurrent(); + PyThread_exit_thread(); } static PyObject * thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) { - PyObject *func, *args, *keyw = NULL; - struct bootstate *boot; - long ident; - - if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, - &func, &args, &keyw)) - return NULL; - if (!PyCallable_Check(func)) { - PyErr_SetString(PyExc_TypeError, - "first arg must be callable"); - return NULL; - } - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_TypeError, - "2nd arg must be a tuple"); - return NULL; - } - if (keyw != NULL && !PyDict_Check(keyw)) { - PyErr_SetString(PyExc_TypeError, - "optional 3rd arg must be a dictionary"); - return NULL; - } - boot = PyMem_NEW(struct bootstate, 1); - if (boot == NULL) - return PyErr_NoMemory(); - boot->interp = PyThreadState_GET()->interp; - boot->func = func; - boot->args = args; - boot->keyw = keyw; - boot->tstate = _PyThreadState_Prealloc(boot->interp); - if (boot->tstate == NULL) { - PyMem_DEL(boot); - return PyErr_NoMemory(); - } - Py_INCREF(func); - Py_INCREF(args); - Py_XINCREF(keyw); - PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ - ident = PyThread_start_new_thread(t_bootstrap, (void*) boot); - if (ident == -1) { - PyErr_SetString(ThreadError, "can't start new thread"); - Py_DECREF(func); - Py_DECREF(args); - Py_XDECREF(keyw); - PyThreadState_Clear(boot->tstate); - PyMem_DEL(boot); - return NULL; - } - return PyLong_FromLong(ident); + PyObject *func, *args, *keyw = NULL; + struct bootstate *boot; + long ident; + + if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, + &func, &args, &keyw)) + return NULL; + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "first arg must be callable"); + return NULL; + } + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_TypeError, + "2nd arg must be a tuple"); + return NULL; + } + if (keyw != NULL && !PyDict_Check(keyw)) { + PyErr_SetString(PyExc_TypeError, + "optional 3rd arg must be a dictionary"); + return NULL; + } + boot = PyMem_NEW(struct bootstate, 1); + if (boot == NULL) + return PyErr_NoMemory(); + boot->interp = PyThreadState_GET()->interp; + boot->func = func; + boot->args = args; + boot->keyw = keyw; + boot->tstate = _PyThreadState_Prealloc(boot->interp); + if (boot->tstate == NULL) { + PyMem_DEL(boot); + return PyErr_NoMemory(); + } + Py_INCREF(func); + Py_INCREF(args); + Py_XINCREF(keyw); + PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ + ident = PyThread_start_new_thread(t_bootstrap, (void*) boot); + if (ident == -1) { + PyErr_SetString(ThreadError, "can't start new thread"); + Py_DECREF(func); + Py_DECREF(args); + Py_XDECREF(keyw); + PyThreadState_Clear(boot->tstate); + PyMem_DEL(boot); + return NULL; + } + return PyLong_FromLong(ident); } PyDoc_STRVAR(start_new_doc, @@ -534,8 +534,8 @@ printed unless the exception is SystemExit.\n"); static PyObject * thread_PyThread_exit_thread(PyObject *self) { - PyErr_SetNone(PyExc_SystemExit); - return NULL; + PyErr_SetNone(PyExc_SystemExit); + return NULL; } PyDoc_STRVAR(exit_doc, @@ -548,9 +548,9 @@ thread to exit silently unless the exception is caught."); static PyObject * thread_PyThread_interrupt_main(PyObject * self) { - PyErr_SetInterrupt(); - Py_INCREF(Py_None); - return Py_None; + PyErr_SetInterrupt(); + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(interrupt_doc, @@ -564,11 +564,11 @@ A subthread can use this function to interrupt the main thread." static PyObject * thread_PyThread_exit_prog(PyObject *self, PyObject *args) { - int sts; - if (!PyArg_ParseTuple(args, "i:exit_prog", &sts)) - return NULL; - Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */ - for (;;) { } /* Should not be reached */ + int sts; + if (!PyArg_ParseTuple(args, "i:exit_prog", &sts)) + return NULL; + Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */ + for (;;) { } /* Should not be reached */ } #endif @@ -577,7 +577,7 @@ static lockobject *newlockobject(void); static PyObject * thread_PyThread_allocate_lock(PyObject *self) { - return (PyObject *) newlockobject(); + return (PyObject *) newlockobject(); } PyDoc_STRVAR(allocate_doc, @@ -589,13 +589,13 @@ Create a new lock object. See LockType.__doc__ for information about locks."); static PyObject * thread_get_ident(PyObject *self) { - long ident; - ident = PyThread_get_thread_ident(); - if (ident == -1) { - PyErr_SetString(ThreadError, "no current thread ident"); - return NULL; - } - return PyLong_FromLong(ident); + long ident; + ident = PyThread_get_thread_ident(); + if (ident == -1) { + PyErr_SetString(ThreadError, "no current thread ident"); + return NULL; + } + return PyLong_FromLong(ident); } PyDoc_STRVAR(get_ident_doc, @@ -612,35 +612,35 @@ A thread's identity may be reused for another thread after it exits."); static PyObject * thread_stack_size(PyObject *self, PyObject *args) { - size_t old_size; - Py_ssize_t new_size = 0; - int rc; - - if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size)) - return NULL; - - if (new_size < 0) { - PyErr_SetString(PyExc_ValueError, - "size must be 0 or a positive value"); - return NULL; - } - - old_size = PyThread_get_stacksize(); - - rc = PyThread_set_stacksize((size_t) new_size); - if (rc == -1) { - PyErr_Format(PyExc_ValueError, - "size not valid: %zd bytes", - new_size); - return NULL; - } - if (rc == -2) { - PyErr_SetString(ThreadError, - "setting stack size not supported"); - return NULL; - } - - return PyLong_FromSsize_t((Py_ssize_t) old_size); + size_t old_size; + Py_ssize_t new_size = 0; + int rc; + + if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size)) + return NULL; + + if (new_size < 0) { + PyErr_SetString(PyExc_ValueError, + "size must be 0 or a positive value"); + return NULL; + } + + old_size = PyThread_get_stacksize(); + + rc = PyThread_set_stacksize((size_t) new_size); + if (rc == -1) { + PyErr_Format(PyExc_ValueError, + "size not valid: %zd bytes", + new_size); + return NULL; + } + if (rc == -2) { + PyErr_SetString(ThreadError, + "setting stack size not supported"); + return NULL; + } + + return PyLong_FromSsize_t((Py_ssize_t) old_size); } PyDoc_STRVAR(stack_size_doc, @@ -664,32 +664,32 @@ requiring allocation in multiples of the system memory page size\n\ the suggested approach in the absence of more specific information)."); static PyMethodDef thread_methods[] = { - {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, - METH_VARARGS, - start_new_doc}, - {"start_new", (PyCFunction)thread_PyThread_start_new_thread, - METH_VARARGS, - start_new_doc}, - {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock, - METH_NOARGS, allocate_doc}, - {"allocate", (PyCFunction)thread_PyThread_allocate_lock, - METH_NOARGS, allocate_doc}, - {"exit_thread", (PyCFunction)thread_PyThread_exit_thread, - METH_NOARGS, exit_doc}, - {"exit", (PyCFunction)thread_PyThread_exit_thread, - METH_NOARGS, exit_doc}, - {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main, - METH_NOARGS, interrupt_doc}, - {"get_ident", (PyCFunction)thread_get_ident, - METH_NOARGS, get_ident_doc}, - {"stack_size", (PyCFunction)thread_stack_size, - METH_VARARGS, - stack_size_doc}, + {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, + METH_VARARGS, + start_new_doc}, + {"start_new", (PyCFunction)thread_PyThread_start_new_thread, + METH_VARARGS, + start_new_doc}, + {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock, + METH_NOARGS, allocate_doc}, + {"allocate", (PyCFunction)thread_PyThread_allocate_lock, + METH_NOARGS, allocate_doc}, + {"exit_thread", (PyCFunction)thread_PyThread_exit_thread, + METH_NOARGS, exit_doc}, + {"exit", (PyCFunction)thread_PyThread_exit_thread, + METH_NOARGS, exit_doc}, + {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main, + METH_NOARGS, interrupt_doc}, + {"get_ident", (PyCFunction)thread_get_ident, + METH_NOARGS, get_ident_doc}, + {"stack_size", (PyCFunction)thread_stack_size, + METH_VARARGS, + stack_size_doc}, #ifndef NO_EXIT_PROG - {"exit_prog", (PyCFunction)thread_PyThread_exit_prog, - METH_VARARGS}, + {"exit_prog", (PyCFunction)thread_PyThread_exit_prog, + METH_VARARGS}, #endif - {NULL, NULL} /* sentinel */ + {NULL, NULL} /* sentinel */ }; @@ -712,47 +712,47 @@ unlock it. A thread attempting to lock a lock that it has already locked\n\ will block until another thread unlocks it. Deadlocks may ensue."); static struct PyModuleDef threadmodule = { - PyModuleDef_HEAD_INIT, - "_thread", - thread_doc, - -1, - thread_methods, - NULL, - NULL, - NULL, - NULL + PyModuleDef_HEAD_INIT, + "_thread", + thread_doc, + -1, + thread_methods, + NULL, + NULL, + NULL, + NULL }; PyMODINIT_FUNC PyInit__thread(void) { - PyObject *m, *d; - - /* Initialize types: */ - if (PyType_Ready(&localtype) < 0) - return NULL; - if (PyType_Ready(&Locktype) < 0) - return NULL; - - /* Create the module and add the functions */ - m = PyModule_Create(&threadmodule); - if (m == NULL) - return NULL; - - /* Add a symbolic constant */ - d = PyModule_GetDict(m); - ThreadError = PyErr_NewException("_thread.error", NULL, NULL); - PyDict_SetItemString(d, "error", ThreadError); - Locktype.tp_doc = lock_doc; - Py_INCREF(&Locktype); - PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); - - Py_INCREF(&localtype); - if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) - return NULL; - - /* Initialize the C thread library */ - PyThread_init_thread(); - return m; + PyObject *m, *d; + + /* Initialize types: */ + if (PyType_Ready(&localtype) < 0) + return NULL; + if (PyType_Ready(&Locktype) < 0) + return NULL; + + /* Create the module and add the functions */ + m = PyModule_Create(&threadmodule); + if (m == NULL) + return NULL; + + /* Add a symbolic constant */ + d = PyModule_GetDict(m); + ThreadError = PyErr_NewException("_thread.error", NULL, NULL); + PyDict_SetItemString(d, "error", ThreadError); + Locktype.tp_doc = lock_doc; + Py_INCREF(&Locktype); + PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); + + Py_INCREF(&localtype); + if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) + return NULL; + + /* Initialize the C thread library */ + PyThread_init_thread(); + return m; } |