Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(320)

Side by Side Diff: Modules/_threadmodule.c

Issue 15139: Speed up threading.Condition wakeup
Patch Set: Created 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Lib/threading.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « Lib/threading.py ('k') | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7