Mercurial > cpython-lru_cache-weakref
comparison Modules/_threadmodule.c @ 61467:f197407bdba2 3.1
Recorded merge of revisions 81032 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
................
r81032 | antoine.pitrou | 2010-05-09 17:52:27 +0200 (dim., 09 mai 2010) | 9 lines
Recorded merge of revisions 81029 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines
Untabify C files. Will watch buildbots.
........
................
| author | Antoine Pitrou <solipsis@pitrou.net> |
|---|---|
| date | Sun, 09 May 2010 16:14:21 +0000 |
| parents | d7a62c16505b |
| children | 109bde5e41b9 |
comparison
equal
deleted
inserted
replaced
| 61459:f8c19c5f5dd2 | 61467:f197407bdba2 |
|---|---|
| 16 | 16 |
| 17 | 17 |
| 18 /* Lock objects */ | 18 /* Lock objects */ |
| 19 | 19 |
| 20 typedef struct { | 20 typedef struct { |
| 21 PyObject_HEAD | 21 PyObject_HEAD |
| 22 PyThread_type_lock lock_lock; | 22 PyThread_type_lock lock_lock; |
| 23 } lockobject; | 23 } lockobject; |
| 24 | 24 |
| 25 static void | 25 static void |
| 26 lock_dealloc(lockobject *self) | 26 lock_dealloc(lockobject *self) |
| 27 { | 27 { |
| 28 if (self->lock_lock != NULL) { | 28 if (self->lock_lock != NULL) { |
| 29 /* Unlock the lock so it's safe to free it */ | 29 /* Unlock the lock so it's safe to free it */ |
| 30 PyThread_acquire_lock(self->lock_lock, 0); | 30 PyThread_acquire_lock(self->lock_lock, 0); |
| 31 PyThread_release_lock(self->lock_lock); | 31 PyThread_release_lock(self->lock_lock); |
| 32 | 32 |
| 33 PyThread_free_lock(self->lock_lock); | 33 PyThread_free_lock(self->lock_lock); |
| 34 } | 34 } |
| 35 PyObject_Del(self); | 35 PyObject_Del(self); |
| 36 } | 36 } |
| 37 | 37 |
| 38 static PyObject * | 38 static PyObject * |
| 39 lock_PyThread_acquire_lock(lockobject *self, PyObject *args) | 39 lock_PyThread_acquire_lock(lockobject *self, PyObject *args) |
| 40 { | 40 { |
| 41 int i = 1; | 41 int i = 1; |
| 42 | 42 |
| 43 if (!PyArg_ParseTuple(args, "|i:acquire", &i)) | 43 if (!PyArg_ParseTuple(args, "|i:acquire", &i)) |
| 44 return NULL; | 44 return NULL; |
| 45 | 45 |
| 46 Py_BEGIN_ALLOW_THREADS | 46 Py_BEGIN_ALLOW_THREADS |
| 47 i = PyThread_acquire_lock(self->lock_lock, i); | 47 i = PyThread_acquire_lock(self->lock_lock, i); |
| 48 Py_END_ALLOW_THREADS | 48 Py_END_ALLOW_THREADS |
| 49 | 49 |
| 50 return PyBool_FromLong((long)i); | 50 return PyBool_FromLong((long)i); |
| 51 } | 51 } |
| 52 | 52 |
| 53 PyDoc_STRVAR(acquire_doc, | 53 PyDoc_STRVAR(acquire_doc, |
| 54 "acquire([wait]) -> None or bool\n\ | 54 "acquire([wait]) -> None or bool\n\ |
| 55 (acquire_lock() is an obsolete synonym)\n\ | 55 (acquire_lock() is an obsolete synonym)\n\ |
| 62 The blocking operation is not interruptible."); | 62 The blocking operation is not interruptible."); |
| 63 | 63 |
| 64 static PyObject * | 64 static PyObject * |
| 65 lock_PyThread_release_lock(lockobject *self) | 65 lock_PyThread_release_lock(lockobject *self) |
| 66 { | 66 { |
| 67 /* Sanity check: the lock must be locked */ | 67 /* Sanity check: the lock must be locked */ |
| 68 if (PyThread_acquire_lock(self->lock_lock, 0)) { | 68 if (PyThread_acquire_lock(self->lock_lock, 0)) { |
| 69 PyThread_release_lock(self->lock_lock); | 69 PyThread_release_lock(self->lock_lock); |
| 70 PyErr_SetString(ThreadError, "release unlocked lock"); | 70 PyErr_SetString(ThreadError, "release unlocked lock"); |
| 71 return NULL; | 71 return NULL; |
| 72 } | 72 } |
| 73 | 73 |
| 74 PyThread_release_lock(self->lock_lock); | 74 PyThread_release_lock(self->lock_lock); |
| 75 Py_INCREF(Py_None); | 75 Py_INCREF(Py_None); |
| 76 return Py_None; | 76 return Py_None; |
| 77 } | 77 } |
| 78 | 78 |
| 79 PyDoc_STRVAR(release_doc, | 79 PyDoc_STRVAR(release_doc, |
| 80 "release()\n\ | 80 "release()\n\ |
| 81 (release_lock() is an obsolete synonym)\n\ | 81 (release_lock() is an obsolete synonym)\n\ |
| 85 but it needn't be locked by the same thread that unlocks it."); | 85 but it needn't be locked by the same thread that unlocks it."); |
| 86 | 86 |
| 87 static PyObject * | 87 static PyObject * |
| 88 lock_locked_lock(lockobject *self) | 88 lock_locked_lock(lockobject *self) |
| 89 { | 89 { |
| 90 if (PyThread_acquire_lock(self->lock_lock, 0)) { | 90 if (PyThread_acquire_lock(self->lock_lock, 0)) { |
| 91 PyThread_release_lock(self->lock_lock); | 91 PyThread_release_lock(self->lock_lock); |
| 92 return PyBool_FromLong(0L); | 92 return PyBool_FromLong(0L); |
| 93 } | 93 } |
| 94 return PyBool_FromLong(1L); | 94 return PyBool_FromLong(1L); |
| 95 } | 95 } |
| 96 | 96 |
| 97 PyDoc_STRVAR(locked_doc, | 97 PyDoc_STRVAR(locked_doc, |
| 98 "locked() -> bool\n\ | 98 "locked() -> bool\n\ |
| 99 (locked_lock() is an obsolete synonym)\n\ | 99 (locked_lock() is an obsolete synonym)\n\ |
| 100 \n\ | 100 \n\ |
| 101 Return whether the lock is in the locked state."); | 101 Return whether the lock is in the locked state."); |
| 102 | 102 |
| 103 static PyMethodDef lock_methods[] = { | 103 static PyMethodDef lock_methods[] = { |
| 104 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, | 104 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, |
| 105 METH_VARARGS, acquire_doc}, | 105 METH_VARARGS, acquire_doc}, |
| 106 {"acquire", (PyCFunction)lock_PyThread_acquire_lock, | 106 {"acquire", (PyCFunction)lock_PyThread_acquire_lock, |
| 107 METH_VARARGS, acquire_doc}, | 107 METH_VARARGS, acquire_doc}, |
| 108 {"release_lock", (PyCFunction)lock_PyThread_release_lock, | 108 {"release_lock", (PyCFunction)lock_PyThread_release_lock, |
| 109 METH_NOARGS, release_doc}, | 109 METH_NOARGS, release_doc}, |
| 110 {"release", (PyCFunction)lock_PyThread_release_lock, | 110 {"release", (PyCFunction)lock_PyThread_release_lock, |
| 111 METH_NOARGS, release_doc}, | 111 METH_NOARGS, release_doc}, |
| 112 {"locked_lock", (PyCFunction)lock_locked_lock, | 112 {"locked_lock", (PyCFunction)lock_locked_lock, |
| 113 METH_NOARGS, locked_doc}, | 113 METH_NOARGS, locked_doc}, |
| 114 {"locked", (PyCFunction)lock_locked_lock, | 114 {"locked", (PyCFunction)lock_locked_lock, |
| 115 METH_NOARGS, locked_doc}, | 115 METH_NOARGS, locked_doc}, |
| 116 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, | 116 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, |
| 117 METH_VARARGS, acquire_doc}, | 117 METH_VARARGS, acquire_doc}, |
| 118 {"__exit__", (PyCFunction)lock_PyThread_release_lock, | 118 {"__exit__", (PyCFunction)lock_PyThread_release_lock, |
| 119 METH_VARARGS, release_doc}, | 119 METH_VARARGS, release_doc}, |
| 120 {NULL, NULL} /* sentinel */ | 120 {NULL, NULL} /* sentinel */ |
| 121 }; | 121 }; |
| 122 | 122 |
| 123 static PyTypeObject Locktype = { | 123 static PyTypeObject Locktype = { |
| 124 PyVarObject_HEAD_INIT(&PyType_Type, 0) | 124 PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| 125 "_thread.lock", /*tp_name*/ | 125 "_thread.lock", /*tp_name*/ |
| 126 sizeof(lockobject), /*tp_size*/ | 126 sizeof(lockobject), /*tp_size*/ |
| 127 0, /*tp_itemsize*/ | 127 0, /*tp_itemsize*/ |
| 128 /* methods */ | 128 /* methods */ |
| 129 (destructor)lock_dealloc, /*tp_dealloc*/ | 129 (destructor)lock_dealloc, /*tp_dealloc*/ |
| 130 0, /*tp_print*/ | 130 0, /*tp_print*/ |
| 131 0, /*tp_getattr*/ | 131 0, /*tp_getattr*/ |
| 132 0, /*tp_setattr*/ | 132 0, /*tp_setattr*/ |
| 133 0, /*tp_reserved*/ | 133 0, /*tp_reserved*/ |
| 134 0, /*tp_repr*/ | 134 0, /*tp_repr*/ |
| 135 0, /*tp_as_number*/ | 135 0, /*tp_as_number*/ |
| 136 0, /*tp_as_sequence*/ | 136 0, /*tp_as_sequence*/ |
| 137 0, /*tp_as_mapping*/ | 137 0, /*tp_as_mapping*/ |
| 138 0, /*tp_hash*/ | 138 0, /*tp_hash*/ |
| 139 0, /*tp_call*/ | 139 0, /*tp_call*/ |
| 140 0, /*tp_str*/ | 140 0, /*tp_str*/ |
| 141 0, /*tp_getattro*/ | 141 0, /*tp_getattro*/ |
| 142 0, /*tp_setattro*/ | 142 0, /*tp_setattro*/ |
| 143 0, /*tp_as_buffer*/ | 143 0, /*tp_as_buffer*/ |
| 144 Py_TPFLAGS_DEFAULT, /*tp_flags*/ | 144 Py_TPFLAGS_DEFAULT, /*tp_flags*/ |
| 145 0, /*tp_doc*/ | 145 0, /*tp_doc*/ |
| 146 0, /*tp_traverse*/ | 146 0, /*tp_traverse*/ |
| 147 0, /*tp_clear*/ | 147 0, /*tp_clear*/ |
| 148 0, /*tp_richcompare*/ | 148 0, /*tp_richcompare*/ |
| 149 0, /*tp_weaklistoffset*/ | 149 0, /*tp_weaklistoffset*/ |
| 150 0, /*tp_iter*/ | 150 0, /*tp_iter*/ |
| 151 0, /*tp_iternext*/ | 151 0, /*tp_iternext*/ |
| 152 lock_methods, /*tp_methods*/ | 152 lock_methods, /*tp_methods*/ |
| 153 }; | 153 }; |
| 154 | 154 |
| 155 static lockobject * | 155 static lockobject * |
| 156 newlockobject(void) | 156 newlockobject(void) |
| 157 { | 157 { |
| 158 lockobject *self; | 158 lockobject *self; |
| 159 self = PyObject_New(lockobject, &Locktype); | 159 self = PyObject_New(lockobject, &Locktype); |
| 160 if (self == NULL) | 160 if (self == NULL) |
| 161 return NULL; | 161 return NULL; |
| 162 self->lock_lock = PyThread_allocate_lock(); | 162 self->lock_lock = PyThread_allocate_lock(); |
| 163 if (self->lock_lock == NULL) { | 163 if (self->lock_lock == NULL) { |
| 164 Py_DECREF(self); | 164 Py_DECREF(self); |
| 165 PyErr_SetString(ThreadError, "can't allocate lock"); | 165 PyErr_SetString(ThreadError, "can't allocate lock"); |
| 166 return NULL; | 166 return NULL; |
| 167 } | 167 } |
| 168 return self; | 168 return self; |
| 169 } | 169 } |
| 170 | 170 |
| 171 /* Thread-local objects */ | 171 /* Thread-local objects */ |
| 172 | 172 |
| 173 #include "structmember.h" | 173 #include "structmember.h" |
| 174 | 174 |
| 175 typedef struct { | 175 typedef struct { |
| 176 PyObject_HEAD | 176 PyObject_HEAD |
| 177 PyObject *key; | 177 PyObject *key; |
| 178 PyObject *args; | 178 PyObject *args; |
| 179 PyObject *kw; | 179 PyObject *kw; |
| 180 PyObject *dict; | 180 PyObject *dict; |
| 181 } localobject; | 181 } localobject; |
| 182 | 182 |
| 183 static PyObject * | 183 static PyObject * |
| 184 local_new(PyTypeObject *type, PyObject *args, PyObject *kw) | 184 local_new(PyTypeObject *type, PyObject *args, PyObject *kw) |
| 185 { | 185 { |
| 186 localobject *self; | 186 localobject *self; |
| 187 PyObject *tdict; | 187 PyObject *tdict; |
| 188 | 188 |
| 189 if (type->tp_init == PyBaseObject_Type.tp_init | 189 if (type->tp_init == PyBaseObject_Type.tp_init |
| 190 && ((args && PyObject_IsTrue(args)) | 190 && ((args && PyObject_IsTrue(args)) |
| 191 || (kw && PyObject_IsTrue(kw)))) { | 191 || (kw && PyObject_IsTrue(kw)))) { |
| 192 PyErr_SetString(PyExc_TypeError, | 192 PyErr_SetString(PyExc_TypeError, |
| 193 "Initialization arguments are not supported"); | 193 "Initialization arguments are not supported"); |
| 194 return NULL; | 194 return NULL; |
| 195 } | 195 } |
| 196 | 196 |
| 197 self = (localobject *)type->tp_alloc(type, 0); | 197 self = (localobject *)type->tp_alloc(type, 0); |
| 198 if (self == NULL) | 198 if (self == NULL) |
| 199 return NULL; | 199 return NULL; |
| 200 | 200 |
| 201 Py_XINCREF(args); | 201 Py_XINCREF(args); |
| 202 self->args = args; | 202 self->args = args; |
| 203 Py_XINCREF(kw); | 203 Py_XINCREF(kw); |
| 204 self->kw = kw; | 204 self->kw = kw; |
| 205 self->dict = NULL; /* making sure */ | 205 self->dict = NULL; /* making sure */ |
| 206 self->key = PyUnicode_FromFormat("thread.local.%p", self); | 206 self->key = PyUnicode_FromFormat("thread.local.%p", self); |
| 207 if (self->key == NULL) | 207 if (self->key == NULL) |
| 208 goto err; | 208 goto err; |
| 209 | 209 |
| 210 self->dict = PyDict_New(); | 210 self->dict = PyDict_New(); |
| 211 if (self->dict == NULL) | 211 if (self->dict == NULL) |
| 212 goto err; | 212 goto err; |
| 213 | 213 |
| 214 tdict = PyThreadState_GetDict(); | 214 tdict = PyThreadState_GetDict(); |
| 215 if (tdict == NULL) { | 215 if (tdict == NULL) { |
| 216 PyErr_SetString(PyExc_SystemError, | 216 PyErr_SetString(PyExc_SystemError, |
| 217 "Couldn't get thread-state dictionary"); | 217 "Couldn't get thread-state dictionary"); |
| 218 goto err; | 218 goto err; |
| 219 } | 219 } |
| 220 | 220 |
| 221 if (PyDict_SetItem(tdict, self->key, self->dict) < 0) | 221 if (PyDict_SetItem(tdict, self->key, self->dict) < 0) |
| 222 goto err; | 222 goto err; |
| 223 | 223 |
| 224 return (PyObject *)self; | 224 return (PyObject *)self; |
| 225 | 225 |
| 226 err: | 226 err: |
| 227 Py_DECREF(self); | 227 Py_DECREF(self); |
| 228 return NULL; | 228 return NULL; |
| 229 } | 229 } |
| 230 | 230 |
| 231 static int | 231 static int |
| 232 local_traverse(localobject *self, visitproc visit, void *arg) | 232 local_traverse(localobject *self, visitproc visit, void *arg) |
| 233 { | 233 { |
| 234 Py_VISIT(self->args); | 234 Py_VISIT(self->args); |
| 235 Py_VISIT(self->kw); | 235 Py_VISIT(self->kw); |
| 236 Py_VISIT(self->dict); | 236 Py_VISIT(self->dict); |
| 237 return 0; | 237 return 0; |
| 238 } | 238 } |
| 239 | 239 |
| 240 static int | 240 static int |
| 241 local_clear(localobject *self) | 241 local_clear(localobject *self) |
| 242 { | 242 { |
| 243 Py_CLEAR(self->args); | 243 Py_CLEAR(self->args); |
| 244 Py_CLEAR(self->kw); | 244 Py_CLEAR(self->kw); |
| 245 Py_CLEAR(self->dict); | 245 Py_CLEAR(self->dict); |
| 246 return 0; | 246 return 0; |
| 247 } | 247 } |
| 248 | 248 |
| 249 static void | 249 static void |
| 250 local_dealloc(localobject *self) | 250 local_dealloc(localobject *self) |
| 251 { | 251 { |
| 252 PyThreadState *tstate; | 252 PyThreadState *tstate; |
| 253 if (self->key | 253 if (self->key |
| 254 && (tstate = PyThreadState_Get()) | 254 && (tstate = PyThreadState_Get()) |
| 255 && tstate->interp) { | 255 && tstate->interp) { |
| 256 for(tstate = PyInterpreterState_ThreadHead(tstate->interp); | 256 for(tstate = PyInterpreterState_ThreadHead(tstate->interp); |
| 257 tstate; | 257 tstate; |
| 258 tstate = PyThreadState_Next(tstate)) | 258 tstate = PyThreadState_Next(tstate)) |
| 259 if (tstate->dict && | 259 if (tstate->dict && |
| 260 PyDict_GetItem(tstate->dict, self->key)) | 260 PyDict_GetItem(tstate->dict, self->key)) |
| 261 PyDict_DelItem(tstate->dict, self->key); | 261 PyDict_DelItem(tstate->dict, self->key); |
| 262 } | 262 } |
| 263 | 263 |
| 264 Py_XDECREF(self->key); | 264 Py_XDECREF(self->key); |
| 265 local_clear(self); | 265 local_clear(self); |
| 266 Py_TYPE(self)->tp_free((PyObject*)self); | 266 Py_TYPE(self)->tp_free((PyObject*)self); |
| 267 } | 267 } |
| 268 | 268 |
| 269 static PyObject * | 269 static PyObject * |
| 270 _ldict(localobject *self) | 270 _ldict(localobject *self) |
| 271 { | 271 { |
| 272 PyObject *tdict, *ldict; | 272 PyObject *tdict, *ldict; |
| 273 | 273 |
| 274 tdict = PyThreadState_GetDict(); | 274 tdict = PyThreadState_GetDict(); |
| 275 if (tdict == NULL) { | 275 if (tdict == NULL) { |
| 276 PyErr_SetString(PyExc_SystemError, | 276 PyErr_SetString(PyExc_SystemError, |
| 277 "Couldn't get thread-state dictionary"); | 277 "Couldn't get thread-state dictionary"); |
| 278 return NULL; | 278 return NULL; |
| 279 } | 279 } |
| 280 | 280 |
| 281 ldict = PyDict_GetItem(tdict, self->key); | 281 ldict = PyDict_GetItem(tdict, self->key); |
| 282 if (ldict == NULL) { | 282 if (ldict == NULL) { |
| 283 ldict = PyDict_New(); /* we own ldict */ | 283 ldict = PyDict_New(); /* we own ldict */ |
| 284 | 284 |
| 285 if (ldict == NULL) | 285 if (ldict == NULL) |
| 286 return NULL; | 286 return NULL; |
| 287 else { | 287 else { |
| 288 int i = PyDict_SetItem(tdict, self->key, ldict); | 288 int i = PyDict_SetItem(tdict, self->key, ldict); |
| 289 Py_DECREF(ldict); /* now ldict is borrowed */ | 289 Py_DECREF(ldict); /* now ldict is borrowed */ |
| 290 if (i < 0) | 290 if (i < 0) |
| 291 return NULL; | 291 return NULL; |
| 292 } | 292 } |
| 293 | 293 |
| 294 Py_CLEAR(self->dict); | 294 Py_CLEAR(self->dict); |
| 295 Py_INCREF(ldict); | 295 Py_INCREF(ldict); |
| 296 self->dict = ldict; /* still borrowed */ | 296 self->dict = ldict; /* still borrowed */ |
| 297 | 297 |
| 298 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && | 298 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && |
| 299 Py_TYPE(self)->tp_init((PyObject*)self, | 299 Py_TYPE(self)->tp_init((PyObject*)self, |
| 300 self->args, self->kw) < 0) { | 300 self->args, self->kw) < 0) { |
| 301 /* we need to get rid of ldict from thread so | 301 /* we need to get rid of ldict from thread so |
| 302 we create a new one the next time we do an attr | 302 we create a new one the next time we do an attr |
| 303 acces */ | 303 acces */ |
| 304 PyDict_DelItem(tdict, self->key); | 304 PyDict_DelItem(tdict, self->key); |
| 305 return NULL; | 305 return NULL; |
| 306 } | 306 } |
| 307 | 307 |
| 308 } | 308 } |
| 309 | 309 |
| 310 /* The call to tp_init above may have caused another thread to run. | 310 /* The call to tp_init above may have caused another thread to run. |
| 311 Install our ldict again. */ | 311 Install our ldict again. */ |
| 312 if (self->dict != ldict) { | 312 if (self->dict != ldict) { |
| 313 Py_CLEAR(self->dict); | 313 Py_CLEAR(self->dict); |
| 314 Py_INCREF(ldict); | 314 Py_INCREF(ldict); |
| 315 self->dict = ldict; | 315 self->dict = ldict; |
| 316 } | 316 } |
| 317 | 317 |
| 318 return ldict; | 318 return ldict; |
| 319 } | 319 } |
| 320 | 320 |
| 321 static int | 321 static int |
| 322 local_setattro(localobject *self, PyObject *name, PyObject *v) | 322 local_setattro(localobject *self, PyObject *name, PyObject *v) |
| 323 { | 323 { |
| 324 PyObject *ldict; | 324 PyObject *ldict; |
| 325 | 325 |
| 326 ldict = _ldict(self); | 326 ldict = _ldict(self); |
| 327 if (ldict == NULL) | 327 if (ldict == NULL) |
| 328 return -1; | 328 return -1; |
| 329 | 329 |
| 330 return PyObject_GenericSetAttr((PyObject *)self, name, v); | 330 return PyObject_GenericSetAttr((PyObject *)self, name, v); |
| 331 } | 331 } |
| 332 | 332 |
| 333 static PyObject * | 333 static PyObject * |
| 334 local_getdict(localobject *self, void *closure) | 334 local_getdict(localobject *self, void *closure) |
| 335 { | 335 { |
| 336 if (self->dict == NULL) { | 336 if (self->dict == NULL) { |
| 337 PyErr_SetString(PyExc_AttributeError, "__dict__"); | 337 PyErr_SetString(PyExc_AttributeError, "__dict__"); |
| 338 return NULL; | 338 return NULL; |
| 339 } | 339 } |
| 340 | 340 |
| 341 Py_INCREF(self->dict); | 341 Py_INCREF(self->dict); |
| 342 return self->dict; | 342 return self->dict; |
| 343 } | 343 } |
| 344 | 344 |
| 345 static PyGetSetDef local_getset[] = { | 345 static PyGetSetDef local_getset[] = { |
| 346 {"__dict__", (getter)local_getdict, (setter)NULL, | 346 {"__dict__", (getter)local_getdict, (setter)NULL, |
| 347 "Local-data dictionary", NULL}, | 347 "Local-data dictionary", NULL}, |
| 348 {NULL} /* Sentinel */ | 348 {NULL} /* Sentinel */ |
| 349 }; | 349 }; |
| 350 | 350 |
| 351 static PyObject *local_getattro(localobject *, PyObject *); | 351 static PyObject *local_getattro(localobject *, PyObject *); |
| 352 | 352 |
| 353 static PyTypeObject localtype = { | 353 static PyTypeObject localtype = { |
| 354 PyVarObject_HEAD_INIT(NULL, 0) | 354 PyVarObject_HEAD_INIT(NULL, 0) |
| 355 /* tp_name */ "_thread._local", | 355 /* tp_name */ "_thread._local", |
| 356 /* tp_basicsize */ sizeof(localobject), | 356 /* tp_basicsize */ sizeof(localobject), |
| 357 /* tp_itemsize */ 0, | 357 /* tp_itemsize */ 0, |
| 358 /* tp_dealloc */ (destructor)local_dealloc, | 358 /* tp_dealloc */ (destructor)local_dealloc, |
| 359 /* tp_print */ 0, | 359 /* tp_print */ 0, |
| 360 /* tp_getattr */ 0, | 360 /* tp_getattr */ 0, |
| 361 /* tp_setattr */ 0, | 361 /* tp_setattr */ 0, |
| 362 /* tp_reserved */ 0, | 362 /* tp_reserved */ 0, |
| 363 /* tp_repr */ 0, | 363 /* tp_repr */ 0, |
| 364 /* tp_as_number */ 0, | 364 /* tp_as_number */ 0, |
| 365 /* tp_as_sequence */ 0, | 365 /* tp_as_sequence */ 0, |
| 366 /* tp_as_mapping */ 0, | 366 /* tp_as_mapping */ 0, |
| 367 /* tp_hash */ 0, | 367 /* tp_hash */ 0, |
| 368 /* tp_call */ 0, | 368 /* tp_call */ 0, |
| 369 /* tp_str */ 0, | 369 /* tp_str */ 0, |
| 370 /* tp_getattro */ (getattrofunc)local_getattro, | 370 /* tp_getattro */ (getattrofunc)local_getattro, |
| 371 /* tp_setattro */ (setattrofunc)local_setattro, | 371 /* tp_setattro */ (setattrofunc)local_setattro, |
| 372 /* tp_as_buffer */ 0, | 372 /* tp_as_buffer */ 0, |
| 373 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | 373 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, |
| 374 /* tp_doc */ "Thread-local data", | 374 /* tp_doc */ "Thread-local data", |
| 375 /* tp_traverse */ (traverseproc)local_traverse, | 375 /* tp_traverse */ (traverseproc)local_traverse, |
| 376 /* tp_clear */ (inquiry)local_clear, | 376 /* tp_clear */ (inquiry)local_clear, |
| 377 /* tp_richcompare */ 0, | 377 /* tp_richcompare */ 0, |
| 378 /* tp_weaklistoffset */ 0, | 378 /* tp_weaklistoffset */ 0, |
| 379 /* tp_iter */ 0, | 379 /* tp_iter */ 0, |
| 380 /* tp_iternext */ 0, | 380 /* tp_iternext */ 0, |
| 381 /* tp_methods */ 0, | 381 /* tp_methods */ 0, |
| 382 /* tp_members */ 0, | 382 /* tp_members */ 0, |
| 383 /* tp_getset */ local_getset, | 383 /* tp_getset */ local_getset, |
| 384 /* tp_base */ 0, | 384 /* tp_base */ 0, |
| 385 /* tp_dict */ 0, /* internal use */ | 385 /* tp_dict */ 0, /* internal use */ |
| 386 /* tp_descr_get */ 0, | 386 /* tp_descr_get */ 0, |
| 387 /* tp_descr_set */ 0, | 387 /* tp_descr_set */ 0, |
| 388 /* tp_dictoffset */ offsetof(localobject, dict), | 388 /* tp_dictoffset */ offsetof(localobject, dict), |
| 389 /* tp_init */ 0, | 389 /* tp_init */ 0, |
| 390 /* tp_alloc */ 0, | 390 /* tp_alloc */ 0, |
| 391 /* tp_new */ local_new, | 391 /* tp_new */ local_new, |
| 392 /* tp_free */ 0, /* Low-level free-mem routine */ | 392 /* tp_free */ 0, /* Low-level free-mem routine */ |
| 393 /* tp_is_gc */ 0, /* For PyObject_IS_GC */ | 393 /* tp_is_gc */ 0, /* For PyObject_IS_GC */ |
| 394 }; | 394 }; |
| 395 | 395 |
| 396 static PyObject * | 396 static PyObject * |
| 397 local_getattro(localobject *self, PyObject *name) | 397 local_getattro(localobject *self, PyObject *name) |
| 398 { | 398 { |
| 399 PyObject *ldict, *value; | 399 PyObject *ldict, *value; |
| 400 | 400 |
| 401 ldict = _ldict(self); | 401 ldict = _ldict(self); |
| 402 if (ldict == NULL) | 402 if (ldict == NULL) |
| 403 return NULL; | 403 return NULL; |
| 404 | 404 |
| 405 if (Py_TYPE(self) != &localtype) | 405 if (Py_TYPE(self) != &localtype) |
| 406 /* use generic lookup for subtypes */ | 406 /* use generic lookup for subtypes */ |
| 407 return PyObject_GenericGetAttr((PyObject *)self, name); | 407 return PyObject_GenericGetAttr((PyObject *)self, name); |
| 408 | 408 |
| 409 /* Optimization: just look in dict ourselves */ | 409 /* Optimization: just look in dict ourselves */ |
| 410 value = PyDict_GetItem(ldict, name); | 410 value = PyDict_GetItem(ldict, name); |
| 411 if (value == NULL) | 411 if (value == NULL) |
| 412 /* Fall back on generic to get __class__ and __dict__ */ | 412 /* Fall back on generic to get __class__ and __dict__ */ |
| 413 return PyObject_GenericGetAttr((PyObject *)self, name); | 413 return PyObject_GenericGetAttr((PyObject *)self, name); |
| 414 | 414 |
| 415 Py_INCREF(value); | 415 Py_INCREF(value); |
| 416 return value; | 416 return value; |
| 417 } | 417 } |
| 418 | 418 |
| 419 /* Module functions */ | 419 /* Module functions */ |
| 420 | 420 |
| 421 struct bootstate { | 421 struct bootstate { |
| 422 PyInterpreterState *interp; | 422 PyInterpreterState *interp; |
| 423 PyObject *func; | 423 PyObject *func; |
| 424 PyObject *args; | 424 PyObject *args; |
| 425 PyObject *keyw; | 425 PyObject *keyw; |
| 426 PyThreadState *tstate; | 426 PyThreadState *tstate; |
| 427 }; | 427 }; |
| 428 | 428 |
| 429 static void | 429 static void |
| 430 t_bootstrap(void *boot_raw) | 430 t_bootstrap(void *boot_raw) |
| 431 { | 431 { |
| 432 struct bootstate *boot = (struct bootstate *) boot_raw; | 432 struct bootstate *boot = (struct bootstate *) boot_raw; |
| 433 PyThreadState *tstate; | 433 PyThreadState *tstate; |
| 434 PyObject *res; | 434 PyObject *res; |
| 435 | 435 |
| 436 tstate = boot->tstate; | 436 tstate = boot->tstate; |
| 437 tstate->thread_id = PyThread_get_thread_ident(); | 437 tstate->thread_id = PyThread_get_thread_ident(); |
| 438 _PyThreadState_Init(tstate); | 438 _PyThreadState_Init(tstate); |
| 439 PyEval_AcquireThread(tstate); | 439 PyEval_AcquireThread(tstate); |
| 440 res = PyEval_CallObjectWithKeywords( | 440 res = PyEval_CallObjectWithKeywords( |
| 441 boot->func, boot->args, boot->keyw); | 441 boot->func, boot->args, boot->keyw); |
| 442 if (res == NULL) { | 442 if (res == NULL) { |
| 443 if (PyErr_ExceptionMatches(PyExc_SystemExit)) | 443 if (PyErr_ExceptionMatches(PyExc_SystemExit)) |
| 444 PyErr_Clear(); | 444 PyErr_Clear(); |
| 445 else { | 445 else { |
| 446 PyObject *file; | 446 PyObject *file; |
| 447 PySys_WriteStderr( | 447 PySys_WriteStderr( |
| 448 "Unhandled exception in thread started by "); | 448 "Unhandled exception in thread started by "); |
| 449 file = PySys_GetObject("stderr"); | 449 file = PySys_GetObject("stderr"); |
| 450 if (file != NULL && file != Py_None) | 450 if (file != NULL && file != Py_None) |
| 451 PyFile_WriteObject(boot->func, file, 0); | 451 PyFile_WriteObject(boot->func, file, 0); |
| 452 else | 452 else |
| 453 PyObject_Print(boot->func, stderr, 0); | 453 PyObject_Print(boot->func, stderr, 0); |
| 454 PySys_WriteStderr("\n"); | 454 PySys_WriteStderr("\n"); |
| 455 PyErr_PrintEx(0); | 455 PyErr_PrintEx(0); |
| 456 } | 456 } |
| 457 } | 457 } |
| 458 else | 458 else |
| 459 Py_DECREF(res); | 459 Py_DECREF(res); |
| 460 Py_DECREF(boot->func); | 460 Py_DECREF(boot->func); |
| 461 Py_DECREF(boot->args); | 461 Py_DECREF(boot->args); |
| 462 Py_XDECREF(boot->keyw); | 462 Py_XDECREF(boot->keyw); |
| 463 PyMem_DEL(boot_raw); | 463 PyMem_DEL(boot_raw); |
| 464 PyThreadState_Clear(tstate); | 464 PyThreadState_Clear(tstate); |
| 465 PyThreadState_DeleteCurrent(); | 465 PyThreadState_DeleteCurrent(); |
| 466 PyThread_exit_thread(); | 466 PyThread_exit_thread(); |
| 467 } | 467 } |
| 468 | 468 |
| 469 static PyObject * | 469 static PyObject * |
| 470 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) | 470 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) |
| 471 { | 471 { |
| 472 PyObject *func, *args, *keyw = NULL; | 472 PyObject *func, *args, *keyw = NULL; |
| 473 struct bootstate *boot; | 473 struct bootstate *boot; |
| 474 long ident; | 474 long ident; |
| 475 | 475 |
| 476 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, | 476 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, |
| 477 &func, &args, &keyw)) | 477 &func, &args, &keyw)) |
| 478 return NULL; | 478 return NULL; |
| 479 if (!PyCallable_Check(func)) { | 479 if (!PyCallable_Check(func)) { |
| 480 PyErr_SetString(PyExc_TypeError, | 480 PyErr_SetString(PyExc_TypeError, |
| 481 "first arg must be callable"); | 481 "first arg must be callable"); |
| 482 return NULL; | 482 return NULL; |
| 483 } | 483 } |
| 484 if (!PyTuple_Check(args)) { | 484 if (!PyTuple_Check(args)) { |
| 485 PyErr_SetString(PyExc_TypeError, | 485 PyErr_SetString(PyExc_TypeError, |
| 486 "2nd arg must be a tuple"); | 486 "2nd arg must be a tuple"); |
| 487 return NULL; | 487 return NULL; |
| 488 } | 488 } |
| 489 if (keyw != NULL && !PyDict_Check(keyw)) { | 489 if (keyw != NULL && !PyDict_Check(keyw)) { |
| 490 PyErr_SetString(PyExc_TypeError, | 490 PyErr_SetString(PyExc_TypeError, |
| 491 "optional 3rd arg must be a dictionary"); | 491 "optional 3rd arg must be a dictionary"); |
| 492 return NULL; | 492 return NULL; |
| 493 } | 493 } |
| 494 boot = PyMem_NEW(struct bootstate, 1); | 494 boot = PyMem_NEW(struct bootstate, 1); |
| 495 if (boot == NULL) | 495 if (boot == NULL) |
| 496 return PyErr_NoMemory(); | 496 return PyErr_NoMemory(); |
| 497 boot->interp = PyThreadState_GET()->interp; | 497 boot->interp = PyThreadState_GET()->interp; |
| 498 boot->func = func; | 498 boot->func = func; |
| 499 boot->args = args; | 499 boot->args = args; |
| 500 boot->keyw = keyw; | 500 boot->keyw = keyw; |
| 501 boot->tstate = _PyThreadState_Prealloc(boot->interp); | 501 boot->tstate = _PyThreadState_Prealloc(boot->interp); |
| 502 if (boot->tstate == NULL) { | 502 if (boot->tstate == NULL) { |
| 503 PyMem_DEL(boot); | 503 PyMem_DEL(boot); |
| 504 return PyErr_NoMemory(); | 504 return PyErr_NoMemory(); |
| 505 } | 505 } |
| 506 Py_INCREF(func); | 506 Py_INCREF(func); |
| 507 Py_INCREF(args); | 507 Py_INCREF(args); |
| 508 Py_XINCREF(keyw); | 508 Py_XINCREF(keyw); |
| 509 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ | 509 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ |
| 510 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot); | 510 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot); |
| 511 if (ident == -1) { | 511 if (ident == -1) { |
| 512 PyErr_SetString(ThreadError, "can't start new thread"); | 512 PyErr_SetString(ThreadError, "can't start new thread"); |
| 513 Py_DECREF(func); | 513 Py_DECREF(func); |
| 514 Py_DECREF(args); | 514 Py_DECREF(args); |
| 515 Py_XDECREF(keyw); | 515 Py_XDECREF(keyw); |
| 516 PyThreadState_Clear(boot->tstate); | 516 PyThreadState_Clear(boot->tstate); |
| 517 PyMem_DEL(boot); | 517 PyMem_DEL(boot); |
| 518 return NULL; | 518 return NULL; |
| 519 } | 519 } |
| 520 return PyLong_FromLong(ident); | 520 return PyLong_FromLong(ident); |
| 521 } | 521 } |
| 522 | 522 |
| 523 PyDoc_STRVAR(start_new_doc, | 523 PyDoc_STRVAR(start_new_doc, |
| 524 "start_new_thread(function, args[, kwargs])\n\ | 524 "start_new_thread(function, args[, kwargs])\n\ |
| 525 (start_new() is an obsolete synonym)\n\ | 525 (start_new() is an obsolete synonym)\n\ |
| 532 printed unless the exception is SystemExit.\n"); | 532 printed unless the exception is SystemExit.\n"); |
| 533 | 533 |
| 534 static PyObject * | 534 static PyObject * |
| 535 thread_PyThread_exit_thread(PyObject *self) | 535 thread_PyThread_exit_thread(PyObject *self) |
| 536 { | 536 { |
| 537 PyErr_SetNone(PyExc_SystemExit); | 537 PyErr_SetNone(PyExc_SystemExit); |
| 538 return NULL; | 538 return NULL; |
| 539 } | 539 } |
| 540 | 540 |
| 541 PyDoc_STRVAR(exit_doc, | 541 PyDoc_STRVAR(exit_doc, |
| 542 "exit()\n\ | 542 "exit()\n\ |
| 543 (PyThread_exit_thread() is an obsolete synonym)\n\ | 543 (PyThread_exit_thread() is an obsolete synonym)\n\ |
| 546 thread to exit silently unless the exception is caught."); | 546 thread to exit silently unless the exception is caught."); |
| 547 | 547 |
| 548 static PyObject * | 548 static PyObject * |
| 549 thread_PyThread_interrupt_main(PyObject * self) | 549 thread_PyThread_interrupt_main(PyObject * self) |
| 550 { | 550 { |
| 551 PyErr_SetInterrupt(); | 551 PyErr_SetInterrupt(); |
| 552 Py_INCREF(Py_None); | 552 Py_INCREF(Py_None); |
| 553 return Py_None; | 553 return Py_None; |
| 554 } | 554 } |
| 555 | 555 |
| 556 PyDoc_STRVAR(interrupt_doc, | 556 PyDoc_STRVAR(interrupt_doc, |
| 557 "interrupt_main()\n\ | 557 "interrupt_main()\n\ |
| 558 \n\ | 558 \n\ |
| 562 | 562 |
| 563 #ifndef NO_EXIT_PROG | 563 #ifndef NO_EXIT_PROG |
| 564 static PyObject * | 564 static PyObject * |
| 565 thread_PyThread_exit_prog(PyObject *self, PyObject *args) | 565 thread_PyThread_exit_prog(PyObject *self, PyObject *args) |
| 566 { | 566 { |
| 567 int sts; | 567 int sts; |
| 568 if (!PyArg_ParseTuple(args, "i:exit_prog", &sts)) | 568 if (!PyArg_ParseTuple(args, "i:exit_prog", &sts)) |
| 569 return NULL; | 569 return NULL; |
| 570 Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */ | 570 Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */ |
| 571 for (;;) { } /* Should not be reached */ | 571 for (;;) { } /* Should not be reached */ |
| 572 } | 572 } |
| 573 #endif | 573 #endif |
| 574 | 574 |
| 575 static lockobject *newlockobject(void); | 575 static lockobject *newlockobject(void); |
| 576 | 576 |
| 577 static PyObject * | 577 static PyObject * |
| 578 thread_PyThread_allocate_lock(PyObject *self) | 578 thread_PyThread_allocate_lock(PyObject *self) |
| 579 { | 579 { |
| 580 return (PyObject *) newlockobject(); | 580 return (PyObject *) newlockobject(); |
| 581 } | 581 } |
| 582 | 582 |
| 583 PyDoc_STRVAR(allocate_doc, | 583 PyDoc_STRVAR(allocate_doc, |
| 584 "allocate_lock() -> lock object\n\ | 584 "allocate_lock() -> lock object\n\ |
| 585 (allocate() is an obsolete synonym)\n\ | 585 (allocate() is an obsolete synonym)\n\ |
| 587 Create a new lock object. See LockType.__doc__ for information about locks."); | 587 Create a new lock object. See LockType.__doc__ for information about locks."); |
| 588 | 588 |
| 589 static PyObject * | 589 static PyObject * |
| 590 thread_get_ident(PyObject *self) | 590 thread_get_ident(PyObject *self) |
| 591 { | 591 { |
| 592 long ident; | 592 long ident; |
| 593 ident = PyThread_get_thread_ident(); | 593 ident = PyThread_get_thread_ident(); |
| 594 if (ident == -1) { | 594 if (ident == -1) { |
| 595 PyErr_SetString(ThreadError, "no current thread ident"); | 595 PyErr_SetString(ThreadError, "no current thread ident"); |
| 596 return NULL; | 596 return NULL; |
| 597 } | 597 } |
| 598 return PyLong_FromLong(ident); | 598 return PyLong_FromLong(ident); |
| 599 } | 599 } |
| 600 | 600 |
| 601 PyDoc_STRVAR(get_ident_doc, | 601 PyDoc_STRVAR(get_ident_doc, |
| 602 "get_ident() -> integer\n\ | 602 "get_ident() -> integer\n\ |
| 603 \n\ | 603 \n\ |
| 610 A thread's identity may be reused for another thread after it exits."); | 610 A thread's identity may be reused for another thread after it exits."); |
| 611 | 611 |
| 612 static PyObject * | 612 static PyObject * |
| 613 thread_stack_size(PyObject *self, PyObject *args) | 613 thread_stack_size(PyObject *self, PyObject *args) |
| 614 { | 614 { |
| 615 size_t old_size; | 615 size_t old_size; |
| 616 Py_ssize_t new_size = 0; | 616 Py_ssize_t new_size = 0; |
| 617 int rc; | 617 int rc; |
| 618 | 618 |
| 619 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size)) | 619 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size)) |
| 620 return NULL; | 620 return NULL; |
| 621 | 621 |
| 622 if (new_size < 0) { | 622 if (new_size < 0) { |
| 623 PyErr_SetString(PyExc_ValueError, | 623 PyErr_SetString(PyExc_ValueError, |
| 624 "size must be 0 or a positive value"); | 624 "size must be 0 or a positive value"); |
| 625 return NULL; | 625 return NULL; |
| 626 } | 626 } |
| 627 | 627 |
| 628 old_size = PyThread_get_stacksize(); | 628 old_size = PyThread_get_stacksize(); |
| 629 | 629 |
| 630 rc = PyThread_set_stacksize((size_t) new_size); | 630 rc = PyThread_set_stacksize((size_t) new_size); |
| 631 if (rc == -1) { | 631 if (rc == -1) { |
| 632 PyErr_Format(PyExc_ValueError, | 632 PyErr_Format(PyExc_ValueError, |
| 633 "size not valid: %zd bytes", | 633 "size not valid: %zd bytes", |
| 634 new_size); | 634 new_size); |
| 635 return NULL; | 635 return NULL; |
| 636 } | 636 } |
| 637 if (rc == -2) { | 637 if (rc == -2) { |
| 638 PyErr_SetString(ThreadError, | 638 PyErr_SetString(ThreadError, |
| 639 "setting stack size not supported"); | 639 "setting stack size not supported"); |
| 640 return NULL; | 640 return NULL; |
| 641 } | 641 } |
| 642 | 642 |
| 643 return PyLong_FromSsize_t((Py_ssize_t) old_size); | 643 return PyLong_FromSsize_t((Py_ssize_t) old_size); |
| 644 } | 644 } |
| 645 | 645 |
| 646 PyDoc_STRVAR(stack_size_doc, | 646 PyDoc_STRVAR(stack_size_doc, |
| 647 "stack_size([size]) -> size\n\ | 647 "stack_size([size]) -> size\n\ |
| 648 \n\ | 648 \n\ |
| 662 - platform documentation should be referred to for more information\n\ | 662 - platform documentation should be referred to for more information\n\ |
| 663 (4kB pages are common; using multiples of 4096 for the stack size is\n\ | 663 (4kB pages are common; using multiples of 4096 for the stack size is\n\ |
| 664 the suggested approach in the absence of more specific information)."); | 664 the suggested approach in the absence of more specific information)."); |
| 665 | 665 |
| 666 static PyMethodDef thread_methods[] = { | 666 static PyMethodDef thread_methods[] = { |
| 667 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, | 667 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, |
| 668 METH_VARARGS, | 668 METH_VARARGS, |
| 669 start_new_doc}, | 669 start_new_doc}, |
| 670 {"start_new", (PyCFunction)thread_PyThread_start_new_thread, | 670 {"start_new", (PyCFunction)thread_PyThread_start_new_thread, |
| 671 METH_VARARGS, | 671 METH_VARARGS, |
| 672 start_new_doc}, | 672 start_new_doc}, |
| 673 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock, | 673 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock, |
| 674 METH_NOARGS, allocate_doc}, | 674 METH_NOARGS, allocate_doc}, |
| 675 {"allocate", (PyCFunction)thread_PyThread_allocate_lock, | 675 {"allocate", (PyCFunction)thread_PyThread_allocate_lock, |
| 676 METH_NOARGS, allocate_doc}, | 676 METH_NOARGS, allocate_doc}, |
| 677 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread, | 677 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread, |
| 678 METH_NOARGS, exit_doc}, | 678 METH_NOARGS, exit_doc}, |
| 679 {"exit", (PyCFunction)thread_PyThread_exit_thread, | 679 {"exit", (PyCFunction)thread_PyThread_exit_thread, |
| 680 METH_NOARGS, exit_doc}, | 680 METH_NOARGS, exit_doc}, |
| 681 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main, | 681 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main, |
| 682 METH_NOARGS, interrupt_doc}, | 682 METH_NOARGS, interrupt_doc}, |
| 683 {"get_ident", (PyCFunction)thread_get_ident, | 683 {"get_ident", (PyCFunction)thread_get_ident, |
| 684 METH_NOARGS, get_ident_doc}, | 684 METH_NOARGS, get_ident_doc}, |
| 685 {"stack_size", (PyCFunction)thread_stack_size, | 685 {"stack_size", (PyCFunction)thread_stack_size, |
| 686 METH_VARARGS, | 686 METH_VARARGS, |
| 687 stack_size_doc}, | 687 stack_size_doc}, |
| 688 #ifndef NO_EXIT_PROG | 688 #ifndef NO_EXIT_PROG |
| 689 {"exit_prog", (PyCFunction)thread_PyThread_exit_prog, | 689 {"exit_prog", (PyCFunction)thread_PyThread_exit_prog, |
| 690 METH_VARARGS}, | 690 METH_VARARGS}, |
| 691 #endif | 691 #endif |
| 692 {NULL, NULL} /* sentinel */ | 692 {NULL, NULL} /* sentinel */ |
| 693 }; | 693 }; |
| 694 | 694 |
| 695 | 695 |
| 696 /* Initialization function */ | 696 /* Initialization function */ |
| 697 | 697 |
| 710 A lock is not owned by the thread that locked it; another thread may\n\ | 710 A lock is not owned by the thread that locked it; another thread may\n\ |
| 711 unlock it. A thread attempting to lock a lock that it has already locked\n\ | 711 unlock it. A thread attempting to lock a lock that it has already locked\n\ |
| 712 will block until another thread unlocks it. Deadlocks may ensue."); | 712 will block until another thread unlocks it. Deadlocks may ensue."); |
| 713 | 713 |
| 714 static struct PyModuleDef threadmodule = { | 714 static struct PyModuleDef threadmodule = { |
| 715 PyModuleDef_HEAD_INIT, | 715 PyModuleDef_HEAD_INIT, |
| 716 "_thread", | 716 "_thread", |
| 717 thread_doc, | 717 thread_doc, |
| 718 -1, | 718 -1, |
| 719 thread_methods, | 719 thread_methods, |
| 720 NULL, | 720 NULL, |
| 721 NULL, | 721 NULL, |
| 722 NULL, | 722 NULL, |
| 723 NULL | 723 NULL |
| 724 }; | 724 }; |
| 725 | 725 |
| 726 | 726 |
| 727 PyMODINIT_FUNC | 727 PyMODINIT_FUNC |
| 728 PyInit__thread(void) | 728 PyInit__thread(void) |
| 729 { | 729 { |
| 730 PyObject *m, *d; | 730 PyObject *m, *d; |
| 731 | 731 |
| 732 /* Initialize types: */ | 732 /* Initialize types: */ |
| 733 if (PyType_Ready(&localtype) < 0) | 733 if (PyType_Ready(&localtype) < 0) |
| 734 return NULL; | 734 return NULL; |
| 735 if (PyType_Ready(&Locktype) < 0) | 735 if (PyType_Ready(&Locktype) < 0) |
| 736 return NULL; | 736 return NULL; |
| 737 | 737 |
| 738 /* Create the module and add the functions */ | 738 /* Create the module and add the functions */ |
| 739 m = PyModule_Create(&threadmodule); | 739 m = PyModule_Create(&threadmodule); |
| 740 if (m == NULL) | 740 if (m == NULL) |
| 741 return NULL; | 741 return NULL; |
| 742 | 742 |
| 743 /* Add a symbolic constant */ | 743 /* Add a symbolic constant */ |
| 744 d = PyModule_GetDict(m); | 744 d = PyModule_GetDict(m); |
| 745 ThreadError = PyErr_NewException("_thread.error", NULL, NULL); | 745 ThreadError = PyErr_NewException("_thread.error", NULL, NULL); |
| 746 PyDict_SetItemString(d, "error", ThreadError); | 746 PyDict_SetItemString(d, "error", ThreadError); |
| 747 Locktype.tp_doc = lock_doc; | 747 Locktype.tp_doc = lock_doc; |
| 748 Py_INCREF(&Locktype); | 748 Py_INCREF(&Locktype); |
| 749 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); | 749 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); |
| 750 | 750 |
| 751 Py_INCREF(&localtype); | 751 Py_INCREF(&localtype); |
| 752 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) | 752 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) |
| 753 return NULL; | 753 return NULL; |
| 754 | 754 |
| 755 /* Initialize the C thread library */ | 755 /* Initialize the C thread library */ |
| 756 PyThread_init_thread(); | 756 PyThread_init_thread(); |
| 757 return m; | 757 return m; |
| 758 } | 758 } |
