| OLD | NEW |
| 1 | 1 |
| 2 /* Thread module */ | 2 /* Thread module */ |
| 3 /* Interface to Sjoerd's portable C thread library */ | 3 /* Interface to Sjoerd's portable C thread library */ |
| 4 | 4 |
| 5 #include "Python.h" | 5 #include "Python.h" |
| 6 #include "structmember.h" /* offsetof */ | 6 #include "structmember.h" /* offsetof */ |
| 7 | 7 |
| 8 #ifndef WITH_THREAD | 8 #ifndef WITH_THREAD |
| 9 #error "Error! The rest of Python is not compiled with thread support." | 9 #error "Error! The rest of Python is not compiled with thread support." |
| 10 #error "Rerun configure, adding a --with-threads option." | 10 #error "Rerun configure, adding a --with-threads option." |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 return PyBool_FromLong(0L); | 180 return PyBool_FromLong(0L); |
| 181 } | 181 } |
| 182 return PyBool_FromLong(1L); | 182 return PyBool_FromLong(1L); |
| 183 } | 183 } |
| 184 | 184 |
| 185 PyDoc_STRVAR(locked_doc, | 185 PyDoc_STRVAR(locked_doc, |
| 186 "locked() -> bool\n\ | 186 "locked() -> bool\n\ |
| 187 (locked_lock() is an obsolete synonym)\n\ | 187 (locked_lock() is an obsolete synonym)\n\ |
| 188 \n\ | 188 \n\ |
| 189 Return whether the lock is in the locked state."); | 189 Return whether the lock is in the locked state."); |
| 190 |
| 191 PyDoc_STRVAR(lock_release_save_doc, |
| 192 "_release_save() -> state\n\ |
| 193 \n\ |
| 194 For internal use by `threading.Condition`."); |
| 195 |
| 196 /* restore does nothing, since _acquire_condition was used which did it |
| 197 * automatically |
| 198 */ |
| 199 static PyObject * |
| 200 lock_acquire_restore(lockobject *self, PyObject *args) |
| 201 { |
| 202 Py_RETURN_NONE; |
| 203 } |
| 204 |
| 205 PyDoc_STRVAR(lock_acquire_restore_doc, |
| 206 "_acquire_restore(state) -> None\n\ |
| 207 \n\ |
| 208 For internal use by `threading.Condition`."); |
| 209 |
| 210 /* forward decleration */ |
| 211 static PyObject * |
| 212 lock_acquire_condition(lockobject *self, PyObject *args, PyObject *kwds); |
| 213 |
| 214 PyDoc_STRVAR(lock_acquire_condition_doc, |
| 215 "_acquire_condition(timeout, outer, state) -> None\n\ |
| 216 \n\ |
| 217 For internal use by `threading.Condition`."); |
| 190 | 218 |
| 191 static PyMethodDef lock_methods[] = { | 219 static PyMethodDef lock_methods[] = { |
| 192 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, | 220 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, |
| 193 METH_VARARGS | METH_KEYWORDS, acquire_doc}, | 221 METH_VARARGS | METH_KEYWORDS, acquire_doc}, |
| 194 {"acquire", (PyCFunction)lock_PyThread_acquire_lock, | 222 {"acquire", (PyCFunction)lock_PyThread_acquire_lock, |
| 195 METH_VARARGS | METH_KEYWORDS, acquire_doc}, | 223 METH_VARARGS | METH_KEYWORDS, acquire_doc}, |
| 196 {"release_lock", (PyCFunction)lock_PyThread_release_lock, | 224 {"release_lock", (PyCFunction)lock_PyThread_release_lock, |
| 197 METH_NOARGS, release_doc}, | 225 METH_NOARGS, release_doc}, |
| 198 {"release", (PyCFunction)lock_PyThread_release_lock, | 226 {"release", (PyCFunction)lock_PyThread_release_lock, |
| 199 METH_NOARGS, release_doc}, | 227 METH_NOARGS, release_doc}, |
| 200 {"locked_lock", (PyCFunction)lock_locked_lock, | 228 {"locked_lock", (PyCFunction)lock_locked_lock, |
| 201 METH_NOARGS, locked_doc}, | 229 METH_NOARGS, locked_doc}, |
| 202 {"locked", (PyCFunction)lock_locked_lock, | 230 {"locked", (PyCFunction)lock_locked_lock, |
| 203 METH_NOARGS, locked_doc}, | 231 METH_NOARGS, locked_doc}, |
| 204 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, | 232 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, |
| 205 METH_VARARGS | METH_KEYWORDS, acquire_doc}, | 233 METH_VARARGS | METH_KEYWORDS, acquire_doc}, |
| 206 {"__exit__", (PyCFunction)lock_PyThread_release_lock, | 234 {"__exit__", (PyCFunction)lock_PyThread_release_lock, |
| 207 METH_VARARGS, release_doc}, | 235 METH_VARARGS, release_doc}, |
| 236 {"_release_save", (PyCFunction)lock_PyThread_release_lock, |
| 237 METH_NOARGS, lock_release_save_doc}, |
| 238 {"_acquire_restore", (PyCFunction)lock_acquire_restore, |
| 239 METH_VARARGS, lock_acquire_restore_doc}, |
| 240 {"_acquire_condition", (PyCFunction)lock_acquire_condition, |
| 241 METH_VARARGS, lock_acquire_condition_doc}, |
| 208 {NULL, NULL} /* sentinel */ | 242 {NULL, NULL} /* sentinel */ |
| 209 }; | 243 }; |
| 210 | 244 |
| 211 static PyTypeObject Locktype = { | 245 static PyTypeObject Locktype = { |
| 212 PyVarObject_HEAD_INIT(&PyType_Type, 0) | 246 PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| 213 "_thread.lock", /*tp_name*/ | 247 "_thread.lock", /*tp_name*/ |
| 214 sizeof(lockobject), /*tp_size*/ | 248 sizeof(lockobject), /*tp_size*/ |
| 215 0, /*tp_itemsize*/ | 249 0, /*tp_itemsize*/ |
| 216 /* methods */ | 250 /* methods */ |
| 217 (destructor)lock_dealloc, /*tp_dealloc*/ | 251 (destructor)lock_dealloc, /*tp_dealloc*/ |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 "release()\n\ | 404 "release()\n\ |
| 371 \n\ | 405 \n\ |
| 372 Release the lock, allowing another thread that is blocked waiting for\n\ | 406 Release the lock, allowing another thread that is blocked waiting for\n\ |
| 373 the lock to acquire the lock. The lock must be in the locked state,\n\ | 407 the lock to acquire the lock. The lock must be in the locked state,\n\ |
| 374 and must be locked by the same thread that unlocks it; otherwise a\n\ | 408 and must be locked by the same thread that unlocks it; otherwise a\n\ |
| 375 `RuntimeError` is raised.\n\ | 409 `RuntimeError` is raised.\n\ |
| 376 \n\ | 410 \n\ |
| 377 Do note that if the lock was acquire()d several times in a row by the\n\ | 411 Do note that if the lock was acquire()d several times in a row by the\n\ |
| 378 current thread, release() needs to be called as many times for the lock\n\ | 412 current thread, release() needs to be called as many times for the lock\n\ |
| 379 to be available for other threads."); | 413 to be available for other threads."); |
| 380 | |
| 381 static PyObject * | |
| 382 rlock_acquire_restore(rlockobject *self, PyObject *arg) | |
| 383 { | |
| 384 long owner; | |
| 385 unsigned long count; | |
| 386 int r = 1; | |
| 387 | |
| 388 if (!PyArg_ParseTuple(arg, "kl:_acquire_restore", &count, &owner)) | |
| 389 return NULL; | |
| 390 | |
| 391 if (!PyThread_acquire_lock(self->rlock_lock, 0)) { | |
| 392 Py_BEGIN_ALLOW_THREADS | |
| 393 r = PyThread_acquire_lock(self->rlock_lock, 1); | |
| 394 Py_END_ALLOW_THREADS | |
| 395 } | |
| 396 if (!r) { | |
| 397 PyErr_SetString(ThreadError, "couldn't acquire lock"); | |
| 398 return NULL; | |
| 399 } | |
| 400 assert(self->rlock_count == 0); | |
| 401 self->rlock_owner = owner; | |
| 402 self->rlock_count = count; | |
| 403 Py_RETURN_NONE; | |
| 404 } | |
| 405 | |
| 406 PyDoc_STRVAR(rlock_acquire_restore_doc, | |
| 407 "_acquire_restore(state) -> None\n\ | |
| 408 \n\ | |
| 409 For internal use by `threading.Condition`."); | |
| 410 | 414 |
| 411 static PyObject * | 415 static PyObject * |
| 412 rlock_release_save(rlockobject *self) | 416 rlock_release_save(rlockobject *self) |
| 413 { | 417 { |
| 414 long owner; | 418 long owner; |
| 415 unsigned long count; | 419 unsigned long count; |
| 416 | 420 |
| 417 if (self->rlock_count == 0) { | 421 if (self->rlock_count == 0) { |
| 418 PyErr_SetString(PyExc_RuntimeError, | 422 PyErr_SetString(PyExc_RuntimeError, |
| 419 "cannot release un-acquired lock"); | 423 "cannot release un-acquired lock"); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 } | 483 } |
| 480 | 484 |
| 481 | 485 |
| 482 static PyMethodDef rlock_methods[] = { | 486 static PyMethodDef rlock_methods[] = { |
| 483 {"acquire", (PyCFunction)rlock_acquire, | 487 {"acquire", (PyCFunction)rlock_acquire, |
| 484 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, | 488 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, |
| 485 {"release", (PyCFunction)rlock_release, | 489 {"release", (PyCFunction)rlock_release, |
| 486 METH_NOARGS, rlock_release_doc}, | 490 METH_NOARGS, rlock_release_doc}, |
| 487 {"_is_owned", (PyCFunction)rlock_is_owned, | 491 {"_is_owned", (PyCFunction)rlock_is_owned, |
| 488 METH_NOARGS, rlock_is_owned_doc}, | 492 METH_NOARGS, rlock_is_owned_doc}, |
| 489 {"_acquire_restore", (PyCFunction)rlock_acquire_restore, | 493 {"_acquire_restore", (PyCFunction)lock_acquire_restore, |
| 490 METH_O, rlock_acquire_restore_doc}, | 494 METH_O, lock_acquire_restore_doc}, |
| 491 {"_release_save", (PyCFunction)rlock_release_save, | 495 {"_release_save", (PyCFunction)rlock_release_save, |
| 492 METH_NOARGS, rlock_release_save_doc}, | 496 METH_NOARGS, rlock_release_save_doc}, |
| 493 {"__enter__", (PyCFunction)rlock_acquire, | 497 {"__enter__", (PyCFunction)rlock_acquire, |
| 494 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, | 498 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, |
| 495 {"__exit__", (PyCFunction)rlock_release, | 499 {"__exit__", (PyCFunction)rlock_release, |
| 496 METH_VARARGS, rlock_release_doc}, | 500 METH_VARARGS, rlock_release_doc}, |
| 497 {NULL, NULL} /* sentinel */ | 501 {NULL, NULL} /* sentinel */ |
| 498 }; | 502 }; |
| 499 | 503 |
| 500 | 504 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 if (self == NULL) | 552 if (self == NULL) |
| 549 return NULL; | 553 return NULL; |
| 550 self->lock_lock = PyThread_allocate_lock(); | 554 self->lock_lock = PyThread_allocate_lock(); |
| 551 self->in_weakreflist = NULL; | 555 self->in_weakreflist = NULL; |
| 552 if (self->lock_lock == NULL) { | 556 if (self->lock_lock == NULL) { |
| 553 Py_DECREF(self); | 557 Py_DECREF(self); |
| 554 PyErr_SetString(ThreadError, "can't allocate lock"); | 558 PyErr_SetString(ThreadError, "can't allocate lock"); |
| 555 return NULL; | 559 return NULL; |
| 556 } | 560 } |
| 557 return self; | 561 return self; |
| 562 } |
| 563 |
| 564 static PyObject * |
| 565 lock_acquire_condition(lockobject *self, PyObject *args, PyObject *kwds) |
| 566 { |
| 567 double timeout; |
| 568 PyObject *outer_lock; |
| 569 PyObject *outer_arg; |
| 570 PY_TIMEOUT_T microseconds; |
| 571 PyLockStatus r; |
| 572 |
| 573 if (!PyArg_ParseTuple(args, "dOO:_acquire_condition", &timeout, &outer_lock,
&outer_arg)) |
| 574 return NULL; |
| 575 |
| 576 if (timeout < 0 && timeout != -1) { |
| 577 PyErr_SetString(PyExc_ValueError, "timeout value must be " |
| 578 "strictly positive"); |
| 579 return NULL; |
| 580 } |
| 581 if (timeout == -1) |
| 582 microseconds = -1; |
| 583 else { |
| 584 timeout *= 1e6; |
| 585 if (timeout >= (double) PY_TIMEOUT_MAX) { |
| 586 PyErr_SetString(PyExc_OverflowError, |
| 587 "timeout value is too large"); |
| 588 return NULL; |
| 589 } |
| 590 microseconds = (PY_TIMEOUT_T) timeout; |
| 591 } |
| 592 |
| 593 /* acquire the condition lock _and_ the outer lock before reacquiring the GI
L */ |
| 594 Py_BEGIN_ALLOW_THREADS |
| 595 r = PyThread_acquire_lock_timed(self->lock_lock, microseconds, 1); |
| 596 /* acquire the outer lock if we know it */ |
| 597 if (Py_TYPE(outer_lock) == &Locktype) { |
| 598 PyThread_acquire_lock_timed(((lockobject*)outer_lock)->lock_lock, -1, 0)
; |
| 599 } else if(Py_TYPE(outer_lock) == &RLocktype) { |
| 600 rlockobject *rlock = (rlockobject*)outer_lock; |
| 601 PyThread_acquire_lock_timed(rlock->rlock_lock, -1, 0); |
| 602 } |
| 603 Py_END_ALLOW_THREADS |
| 604 /* and restore the state of the RLock */ |
| 605 if (Py_TYPE(outer_lock) == &RLocktype) { |
| 606 rlockobject *rlock = (rlockobject*)outer_lock; |
| 607 PyArg_ParseTuple(outer_arg, "kl", &rlock->rlock_count, &rlock->rlock_own
er); |
| 608 } |
| 609 |
| 610 if (r == PY_LOCK_INTR) { |
| 611 return NULL; |
| 612 } |
| 613 |
| 614 return PyBool_FromLong(r == PY_LOCK_ACQUIRED); |
| 558 } | 615 } |
| 559 | 616 |
| 560 /* Thread-local objects */ | 617 /* Thread-local objects */ |
| 561 | 618 |
| 562 #include "structmember.h" | 619 #include "structmember.h" |
| 563 | 620 |
| 564 /* Quick overview: | 621 /* Quick overview: |
| 565 | 622 |
| 566 We need to be able to reclaim reference cycles as soon as possible | 623 We need to be able to reclaim reference cycles as soon as possible |
| 567 (both when a thread is being terminated, or a thread-local object | 624 (both when a thread is being terminated, or a thread-local object |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 nb_threads = 0; | 1390 nb_threads = 0; |
| 1334 | 1391 |
| 1335 str_dict = PyUnicode_InternFromString("__dict__"); | 1392 str_dict = PyUnicode_InternFromString("__dict__"); |
| 1336 if (str_dict == NULL) | 1393 if (str_dict == NULL) |
| 1337 return NULL; | 1394 return NULL; |
| 1338 | 1395 |
| 1339 /* Initialize the C thread library */ | 1396 /* Initialize the C thread library */ |
| 1340 PyThread_init_thread(); | 1397 PyThread_init_thread(); |
| 1341 return m; | 1398 return m; |
| 1342 } | 1399 } |
| OLD | NEW |