| 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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 lock_locked_lock(lockobject *self) | 182 lock_locked_lock(lockobject *self) |
| 183 { | 183 { |
| 184 return PyBool_FromLong((long)self->locked); | 184 return PyBool_FromLong((long)self->locked); |
| 185 } | 185 } |
| 186 | 186 |
| 187 PyDoc_STRVAR(locked_doc, | 187 PyDoc_STRVAR(locked_doc, |
| 188 "locked() -> bool\n\ | 188 "locked() -> bool\n\ |
| 189 (locked_lock() is an obsolete synonym)\n\ | 189 (locked_lock() is an obsolete synonym)\n\ |
| 190 \n\ | 190 \n\ |
| 191 Return whether the lock is in the locked state."); | 191 Return whether the lock is in the locked state."); |
| 192 |
| 193 PyDoc_STRVAR(lock_release_save_doc, |
| 194 "_release_save() -> state\n\ |
| 195 \n\ |
| 196 For internal use by `threading.Condition`."); |
| 197 |
| 198 /* restore does nothing, since _acquire_condition was used which did it |
| 199 * automatically |
| 200 */ |
| 201 static PyObject * |
| 202 lock_acquire_restore(lockobject *self, PyObject *args) |
| 203 { |
| 204 Py_RETURN_NONE; |
| 205 } |
| 206 |
| 207 PyDoc_STRVAR(lock_acquire_restore_doc, |
| 208 "_acquire_restore(state) -> None\n\ |
| 209 \n\ |
| 210 For internal use by `threading.Condition`."); |
| 211 |
| 212 /* forward decleration */ |
| 213 static PyObject * |
| 214 lock_acquire_condition(lockobject *self, PyObject *args, PyObject *kwds); |
| 215 |
| 216 PyDoc_STRVAR(lock_acquire_condition_doc, |
| 217 "_acquire_condition(timeout, outer, state) -> None\n\ |
| 218 \n\ |
| 219 For internal use by `threading.Condition`."); |
| 192 | 220 |
| 193 static PyMethodDef lock_methods[] = { | 221 static PyMethodDef lock_methods[] = { |
| 194 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, | 222 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, |
| 195 METH_VARARGS | METH_KEYWORDS, acquire_doc}, | 223 METH_VARARGS | METH_KEYWORDS, acquire_doc}, |
| 196 {"acquire", (PyCFunction)lock_PyThread_acquire_lock, | 224 {"acquire", (PyCFunction)lock_PyThread_acquire_lock, |
| 197 METH_VARARGS | METH_KEYWORDS, acquire_doc}, | 225 METH_VARARGS | METH_KEYWORDS, acquire_doc}, |
| 198 {"release_lock", (PyCFunction)lock_PyThread_release_lock, | 226 {"release_lock", (PyCFunction)lock_PyThread_release_lock, |
| 199 METH_NOARGS, release_doc}, | 227 METH_NOARGS, release_doc}, |
| 200 {"release", (PyCFunction)lock_PyThread_release_lock, | 228 {"release", (PyCFunction)lock_PyThread_release_lock, |
| 201 METH_NOARGS, release_doc}, | 229 METH_NOARGS, release_doc}, |
| 202 {"locked_lock", (PyCFunction)lock_locked_lock, | 230 {"locked_lock", (PyCFunction)lock_locked_lock, |
| 203 METH_NOARGS, locked_doc}, | 231 METH_NOARGS, locked_doc}, |
| 204 {"locked", (PyCFunction)lock_locked_lock, | 232 {"locked", (PyCFunction)lock_locked_lock, |
| 205 METH_NOARGS, locked_doc}, | 233 METH_NOARGS, locked_doc}, |
| 206 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, | 234 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, |
| 207 METH_VARARGS | METH_KEYWORDS, acquire_doc}, | 235 METH_VARARGS | METH_KEYWORDS, acquire_doc}, |
| 208 {"__exit__", (PyCFunction)lock_PyThread_release_lock, | 236 {"__exit__", (PyCFunction)lock_PyThread_release_lock, |
| 209 METH_VARARGS, release_doc}, | 237 METH_VARARGS, release_doc}, |
| 238 {"_release_save", (PyCFunction)lock_PyThread_release_lock, |
| 239 METH_NOARGS, lock_release_save_doc}, |
| 240 {"_acquire_restore", (PyCFunction)lock_acquire_restore, |
| 241 METH_VARARGS, lock_acquire_restore_doc}, |
| 242 {"_acquire_condition", (PyCFunction)lock_acquire_condition, |
| 243 METH_VARARGS, lock_acquire_condition_doc}, |
| 210 {NULL, NULL} /* sentinel */ | 244 {NULL, NULL} /* sentinel */ |
| 211 }; | 245 }; |
| 212 | 246 |
| 213 static PyTypeObject Locktype = { | 247 static PyTypeObject Locktype = { |
| 214 PyVarObject_HEAD_INIT(&PyType_Type, 0) | 248 PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| 215 "_thread.lock", /*tp_name*/ | 249 "_thread.lock", /*tp_name*/ |
| 216 sizeof(lockobject), /*tp_size*/ | 250 sizeof(lockobject), /*tp_size*/ |
| 217 0, /*tp_itemsize*/ | 251 0, /*tp_itemsize*/ |
| 218 /* methods */ | 252 /* methods */ |
| 219 (destructor)lock_dealloc, /*tp_dealloc*/ | 253 (destructor)lock_dealloc, /*tp_dealloc*/ |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 "release()\n\ | 399 "release()\n\ |
| 366 \n\ | 400 \n\ |
| 367 Release the lock, allowing another thread that is blocked waiting for\n\ | 401 Release the lock, allowing another thread that is blocked waiting for\n\ |
| 368 the lock to acquire the lock. The lock must be in the locked state,\n\ | 402 the lock to acquire the lock. The lock must be in the locked state,\n\ |
| 369 and must be locked by the same thread that unlocks it; otherwise a\n\ | 403 and must be locked by the same thread that unlocks it; otherwise a\n\ |
| 370 `RuntimeError` is raised.\n\ | 404 `RuntimeError` is raised.\n\ |
| 371 \n\ | 405 \n\ |
| 372 Do note that if the lock was acquire()d several times in a row by the\n\ | 406 Do note that if the lock was acquire()d several times in a row by the\n\ |
| 373 current thread, release() needs to be called as many times for the lock\n\ | 407 current thread, release() needs to be called as many times for the lock\n\ |
| 374 to be available for other threads."); | 408 to be available for other threads."); |
| 375 | |
| 376 static PyObject * | |
| 377 rlock_acquire_restore(rlockobject *self, PyObject *arg) | |
| 378 { | |
| 379 long owner; | |
| 380 unsigned long count; | |
| 381 int r = 1; | |
| 382 | |
| 383 if (!PyArg_ParseTuple(arg, "kl:_acquire_restore", &count, &owner)) | |
| 384 return NULL; | |
| 385 | |
| 386 if (!PyThread_acquire_lock(self->rlock_lock, 0)) { | |
| 387 Py_BEGIN_ALLOW_THREADS | |
| 388 r = PyThread_acquire_lock(self->rlock_lock, 1); | |
| 389 Py_END_ALLOW_THREADS | |
| 390 } | |
| 391 if (!r) { | |
| 392 PyErr_SetString(ThreadError, "couldn't acquire lock"); | |
| 393 return NULL; | |
| 394 } | |
| 395 assert(self->rlock_count == 0); | |
| 396 self->rlock_owner = owner; | |
| 397 self->rlock_count = count; | |
| 398 Py_RETURN_NONE; | |
| 399 } | |
| 400 | |
| 401 PyDoc_STRVAR(rlock_acquire_restore_doc, | |
| 402 "_acquire_restore(state) -> None\n\ | |
| 403 \n\ | |
| 404 For internal use by `threading.Condition`."); | |
| 405 | 409 |
| 406 static PyObject * | 410 static PyObject * |
| 407 rlock_release_save(rlockobject *self) | 411 rlock_release_save(rlockobject *self) |
| 408 { | 412 { |
| 409 long owner; | 413 long owner; |
| 410 unsigned long count; | 414 unsigned long count; |
| 411 | 415 |
| 412 if (self->rlock_count == 0) { | 416 if (self->rlock_count == 0) { |
| 413 PyErr_SetString(PyExc_RuntimeError, | 417 PyErr_SetString(PyExc_RuntimeError, |
| 414 "cannot release un-acquired lock"); | 418 "cannot release un-acquired lock"); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 } | 478 } |
| 475 | 479 |
| 476 | 480 |
| 477 static PyMethodDef rlock_methods[] = { | 481 static PyMethodDef rlock_methods[] = { |
| 478 {"acquire", (PyCFunction)rlock_acquire, | 482 {"acquire", (PyCFunction)rlock_acquire, |
| 479 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, | 483 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, |
| 480 {"release", (PyCFunction)rlock_release, | 484 {"release", (PyCFunction)rlock_release, |
| 481 METH_NOARGS, rlock_release_doc}, | 485 METH_NOARGS, rlock_release_doc}, |
| 482 {"_is_owned", (PyCFunction)rlock_is_owned, | 486 {"_is_owned", (PyCFunction)rlock_is_owned, |
| 483 METH_NOARGS, rlock_is_owned_doc}, | 487 METH_NOARGS, rlock_is_owned_doc}, |
| 484 {"_acquire_restore", (PyCFunction)rlock_acquire_restore, | 488 {"_acquire_restore", (PyCFunction)lock_acquire_restore, |
| 485 METH_O, rlock_acquire_restore_doc}, | 489 METH_O, lock_acquire_restore_doc}, |
| 486 {"_release_save", (PyCFunction)rlock_release_save, | 490 {"_release_save", (PyCFunction)rlock_release_save, |
| 487 METH_NOARGS, rlock_release_save_doc}, | 491 METH_NOARGS, rlock_release_save_doc}, |
| 488 {"__enter__", (PyCFunction)rlock_acquire, | 492 {"__enter__", (PyCFunction)rlock_acquire, |
| 489 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, | 493 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, |
| 490 {"__exit__", (PyCFunction)rlock_release, | 494 {"__exit__", (PyCFunction)rlock_release, |
| 491 METH_VARARGS, rlock_release_doc}, | 495 METH_VARARGS, rlock_release_doc}, |
| 492 {NULL, NULL} /* sentinel */ | 496 {NULL, NULL} /* sentinel */ |
| 493 }; | 497 }; |
| 494 | 498 |
| 495 | 499 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 return NULL; | 548 return NULL; |
| 545 self->lock_lock = PyThread_allocate_lock(); | 549 self->lock_lock = PyThread_allocate_lock(); |
| 546 self->locked = 0; | 550 self->locked = 0; |
| 547 self->in_weakreflist = NULL; | 551 self->in_weakreflist = NULL; |
| 548 if (self->lock_lock == NULL) { | 552 if (self->lock_lock == NULL) { |
| 549 Py_DECREF(self); | 553 Py_DECREF(self); |
| 550 PyErr_SetString(ThreadError, "can't allocate lock"); | 554 PyErr_SetString(ThreadError, "can't allocate lock"); |
| 551 return NULL; | 555 return NULL; |
| 552 } | 556 } |
| 553 return self; | 557 return self; |
| 558 } |
| 559 |
| 560 static PyObject * |
| 561 lock_acquire_condition(lockobject *self, PyObject *args, PyObject *kwds) |
| 562 { |
| 563 PyObject *timeout_obj; |
| 564 PyObject *outer_lock; |
| 565 PyObject *outer_arg; |
| 566 double timeout; |
| 567 unsigned long count; |
| 568 long owner; |
| 569 PY_TIMEOUT_T microseconds; |
| 570 PyLockStatus r; |
| 571 |
| 572 /* if we can't even parse the arguments, then we cannot re-acquire the outer
lock. But that |
| 573 * is the same if passing wrong arguments to a _aquire_restore method. |
| 574 */ |
| 575 if (!PyArg_ParseTuple(args, "OOO:_acquire_condition", &timeout_obj, &outer_l
ock, &outer_arg)) |
| 576 return NULL; |
| 577 if (Py_TYPE(outer_lock) == &RLocktype) |
| 578 if (!PyArg_ParseTuple(outer_arg, "kl", &count, &owner)) |
| 579 return NULL; |
| 580 |
| 581 /* None is infinite, otherwise a float is the timeout in seconds, negative v
alues |
| 582 * are clipped to zero |
| 583 */ |
| 584 if (timeout_obj == Py_None) { |
| 585 microseconds = -1; |
| 586 } else { |
| 587 timeout = PyFloat_AsDouble(timeout_obj); |
| 588 if (timeout == -1.0 && PyErr_Occurred()) |
| 589 goto ERR; |
| 590 if (timeout > 0.0) { |
| 591 timeout *= 1e6; |
| 592 if (timeout >= (double) PY_TIMEOUT_MAX) { |
| 593 PyErr_SetString(PyExc_OverflowError, |
| 594 "timeout value is too large"); |
| 595 goto ERR; |
| 596 } |
| 597 microseconds = (PY_TIMEOUT_T) timeout; |
| 598 } else |
| 599 microseconds = 0; |
| 600 } |
| 601 |
| 602 r = PY_LOCK_ACQUIRED; |
| 603 goto ACQUIRE; |
| 604 ERR: |
| 605 r = PY_LOCK_INTR; /* just acquire the outer lock and exit with error */ |
| 606 ACQUIRE: |
| 607 /* acquire the condition lock _and_ the outer lock before reacquiring the GI
L */ |
| 608 Py_BEGIN_ALLOW_THREADS |
| 609 if (r == PY_LOCK_ACQUIRED) |
| 610 r = PyThread_acquire_lock_timed(self->lock_lock, microseconds, 1); |
| 611 /* acquire the outer lock if we know it */ |
| 612 if (Py_TYPE(outer_lock) == &Locktype) { |
| 613 PyThread_acquire_lock_timed(((lockobject*)outer_lock)->lock_lock, -1, 0)
; |
| 614 } else if(Py_TYPE(outer_lock) == &RLocktype) { |
| 615 rlockobject *rlock = (rlockobject*)outer_lock; |
| 616 PyThread_acquire_lock_timed(rlock->rlock_lock, -1, 0); |
| 617 } |
| 618 Py_END_ALLOW_THREADS |
| 619 /* and restore the state of the locks */ |
| 620 if (Py_TYPE(outer_lock) == &Locktype) { |
| 621 ((lockobject*)outer_lock)->locked = 1; |
| 622 } else if (Py_TYPE(outer_lock) == &RLocktype) { |
| 623 rlockobject *rlock = (rlockobject*)outer_lock; |
| 624 rlock->rlock_count = count; |
| 625 rlock->rlock_owner = owner; |
| 626 } |
| 627 |
| 628 if (r == PY_LOCK_INTR) { |
| 629 return NULL; |
| 630 } |
| 631 |
| 632 return PyBool_FromLong(r == PY_LOCK_ACQUIRED); |
| 554 } | 633 } |
| 555 | 634 |
| 556 /* Thread-local objects */ | 635 /* Thread-local objects */ |
| 557 | 636 |
| 558 #include "structmember.h" | 637 #include "structmember.h" |
| 559 | 638 |
| 560 /* Quick overview: | 639 /* Quick overview: |
| 561 | 640 |
| 562 We need to be able to reclaim reference cycles as soon as possible | 641 We need to be able to reclaim reference cycles as soon as possible |
| 563 (both when a thread is being terminated, or a thread-local object | 642 (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... |
| 1329 nb_threads = 0; | 1408 nb_threads = 0; |
| 1330 | 1409 |
| 1331 str_dict = PyUnicode_InternFromString("__dict__"); | 1410 str_dict = PyUnicode_InternFromString("__dict__"); |
| 1332 if (str_dict == NULL) | 1411 if (str_dict == NULL) |
| 1333 return NULL; | 1412 return NULL; |
| 1334 | 1413 |
| 1335 /* Initialize the C thread library */ | 1414 /* Initialize the C thread library */ |
| 1336 PyThread_init_thread(); | 1415 PyThread_init_thread(); |
| 1337 return m; | 1416 return m; |
| 1338 } | 1417 } |
| OLD | NEW |