1 2 /* Thread module */ 3 /* Interface to Sjoerd's portable C thread library */ 4 5 #include "Python.h" 6 #include "structmember.h" /* offsetof */ 7 8 #ifndef WITH_THREAD 9 #error "Error! The rest of Python is not compiled with thread support." 10 #error "Rerun configure, adding a --with-threads option." 11 #error "Then run `make clean' followed by `make'." 12 #endif 13 14 #include "pythread.h" 15 16 static PyObject *ThreadError; 17 static PyObject *str_dict; 18 static long nb_threads = 0; 19 20 /* Lock objects */ 21 22 typedef struct { 23 PyObject_HEAD 24 PyThread_type_lock lock_lock; 25 PyObject *in_weakreflist; 26 } lockobject; 27 28 static void 29 lock_dealloc(lockobject *self) 30 { 31 if (self->in_weakreflist != NULL) 32 PyObject_ClearWeakRefs((PyObject *) self); 33 if (self->lock_lock != NULL) { 34 /* Unlock the lock so it's safe to free it */ 35 PyThread_acquire_lock(self->lock_lock, 0); 36 PyThread_release_lock(self->lock_lock); 37 38 PyThread_free_lock(self->lock_lock); 39 } 40 PyObject_Del(self); 41 } 42 43 static PyObject * 44 lock_PyThread_acquire_lock(lockobject *self, PyObject *args) 45 { 46 int i = 1; 47 48 if (!PyArg_ParseTuple(args, "|i:acquire", &i)) 49 return NULL; 50 51 Py_BEGIN_ALLOW_THREADS 52 i = PyThread_acquire_lock(self->lock_lock, i); 53 Py_END_ALLOW_THREADS 54 55 return PyBool_FromLong((long)i); 56 } 57 58 PyDoc_STRVAR(acquire_doc, 59 "acquire([wait]) -> None or bool\n\ 60 (acquire_lock() is an obsolete synonym)\n\ 61 \n\ 62 Lock the lock. Without argument, this blocks if the lock is already\n\ 63 locked (even by the same thread), waiting for another thread to release\n\ 64 the lock, and return None once the lock is acquired.\n\ 65 With an argument, this will only block if the argument is true,\n\ 66 and the return value reflects whether the lock is acquired.\n\ 67 The blocking operation is not interruptible."); 68 69 static PyObject * 70 lock_PyThread_release_lock(lockobject *self) 71 { 72 /* Sanity check: the lock must be locked */ 73 if (PyThread_acquire_lock(self->lock_lock, 0)) { 74 PyThread_release_lock(self->lock_lock); 75 PyErr_SetString(ThreadError, "release unlocked lock"); 76 return NULL; 77 } 78 79 PyThread_release_lock(self->lock_lock); 80 Py_INCREF(Py_None); 81 return Py_None; 82 } 83 84 PyDoc_STRVAR(release_doc, 85 "release()\n\ 86 (release_lock() is an obsolete synonym)\n\ 87 \n\ 88 Release the lock, allowing another thread that is blocked waiting for\n\ 89 the lock to acquire the lock. The lock must be in the locked state,\n\ 90 but it needn't be locked by the same thread that unlocks it."); 91 92 static PyObject * 93 lock_locked_lock(lockobject *self) 94 { 95 if (PyThread_acquire_lock(self->lock_lock, 0)) { 96 PyThread_release_lock(self->lock_lock); 97 return PyBool_FromLong(0L); 98 } 99 return PyBool_FromLong(1L); 100 } 101 102 PyDoc_STRVAR(locked_doc, 103 "locked() -> bool\n\ 104 (locked_lock() is an obsolete synonym)\n\ 105 \n\ 106 Return whether the lock is in the locked state."); 107 108 static PyMethodDef lock_methods[] = { 109 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, 110 METH_VARARGS, acquire_doc}, 111 {"acquire", (PyCFunction)lock_PyThread_acquire_lock, 112 METH_VARARGS, acquire_doc}, 113 {"release_lock", (PyCFunction)lock_PyThread_release_lock, 114 METH_NOARGS, release_doc}, 115 {"release", (PyCFunction)lock_PyThread_release_lock, 116 METH_NOARGS, release_doc}, 117 {"locked_lock", (PyCFunction)lock_locked_lock, 118 METH_NOARGS, locked_doc}, 119 {"locked", (PyCFunction)lock_locked_lock, 120 METH_NOARGS, locked_doc}, 121 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, 122 METH_VARARGS, acquire_doc}, 123 {"__exit__", (PyCFunction)lock_PyThread_release_lock, 124 METH_VARARGS, release_doc}, 125 {NULL} /* sentinel */ 126 }; 127 128 static PyTypeObject Locktype = { 129 PyVarObject_HEAD_INIT(&PyType_Type, 0) 130 "thread.lock", /*tp_name*/ 131 sizeof(lockobject), /*tp_size*/ 132 0, /*tp_itemsize*/ 133 /* methods */ 134 (destructor)lock_dealloc, /*tp_dealloc*/ 135 0, /*tp_print*/ 136 0, /*tp_getattr*/ 137 0, /*tp_setattr*/ 138 0, /*tp_compare*/ 139 0, /*tp_repr*/ 140 0, /* tp_as_number */ 141 0, /* tp_as_sequence */ 142 0, /* tp_as_mapping */ 143 0, /* tp_hash */ 144 0, /* tp_call */ 145 0, /* tp_str */ 146 0, /* tp_getattro */ 147 0, /* tp_setattro */ 148 0, /* tp_as_buffer */ 149 Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 150 0, /* tp_doc */ 151 0, /* tp_traverse */ 152 0, /* tp_clear */ 153 0, /* tp_richcompare */ 154 offsetof(lockobject, in_weakreflist), /* tp_weaklistoffset */ 155 0, /* tp_iter */ 156 0, /* tp_iternext */ 157 lock_methods, /* tp_methods */ 158 }; 159 160 static lockobject * 161 newlockobject(void) 162 { 163 lockobject *self; 164 self = PyObject_New(lockobject, &Locktype); 165 if (self == NULL) 166 return NULL; 167 self->lock_lock = PyThread_allocate_lock(); 168 self->in_weakreflist = NULL; 169 if (self->lock_lock == NULL) { 170 Py_DECREF(self); 171 PyErr_SetString(ThreadError, "can't allocate lock"); 172 return NULL; 173 } 174 return self; 175 } 176 177 /* Thread-local objects */ 178 179 #include "structmember.h" 180 181 /* Quick overview: 182 183 We need to be able to reclaim reference cycles as soon as possible 184 (both when a thread is being terminated, or a thread-local object 185 becomes unreachable from user data). Constraints: 186 - it must not be possible for thread-state dicts to be involved in 187 reference cycles (otherwise the cyclic GC will refuse to consider 188 objects referenced from a reachable thread-state dict, even though 189 local_dealloc would clear them) 190 - the death of a thread-state dict must still imply destruction of the 191 corresponding local dicts in all thread-local objects. 192 193 Our implementation uses small "localdummy" objects in order to break 194 the reference chain. These trivial objects are hashable (using the 195 default scheme of identity hashing) and weakrefable. 196 Each thread-state holds a separate localdummy for each local object 197 (as a /strong reference/), 198 and each thread-local object holds a dict mapping /weak references/ 199 of localdummies to local dicts. 200 201 Therefore: 202 - only the thread-state dict holds a strong reference to the dummies 203 - only the thread-local object holds a strong reference to the local dicts 204 - only outside objects (application- or library-level) hold strong 205 references to the thread-local objects 206 - as soon as a thread-state dict is destroyed, the weakref callbacks of all 207 dummies attached to that thread are called, and destroy the corresponding 208 local dicts from thread-local objects 209 - as soon as a thread-local object is destroyed, its local dicts are 210 destroyed and its dummies are manually removed from all thread states 211 - the GC can do its work correctly when a thread-local object is dangling, 212 without any interference from the thread-state dicts 213 214 As an additional optimization, each localdummy holds a borrowed reference 215 to the corresponding localdict. This borrowed reference is only used 216 by the thread-local object which has created the localdummy, which should 217 guarantee that the localdict still exists when accessed. 218 */ 219 220 typedef struct { 221 PyObject_HEAD 222 PyObject *localdict; /* Borrowed reference! */ 223 PyObject *weakreflist; /* List of weak references to self */ 224 } localdummyobject; 225 226 static void 227 localdummy_dealloc(localdummyobject *self) 228 { 229 if (self->weakreflist != NULL) 230 PyObject_ClearWeakRefs((PyObject *) self); 231 Py_TYPE(self)->tp_free((PyObject*)self); 232 } 233 234 static PyTypeObject localdummytype = { 235 PyVarObject_HEAD_INIT(NULL, 0) 236 /* tp_name */ "_thread._localdummy", 237 /* tp_basicsize */ sizeof(localdummyobject), 238 /* tp_itemsize */ 0, 239 /* tp_dealloc */ (destructor)localdummy_dealloc, 240 /* tp_print */ 0, 241 /* tp_getattr */ 0, 242 /* tp_setattr */ 0, 243 /* tp_reserved */ 0, 244 /* tp_repr */ 0, 245 /* tp_as_number */ 0, 246 /* tp_as_sequence */ 0, 247 /* tp_as_mapping */ 0, 248 /* tp_hash */ 0, 249 /* tp_call */ 0, 250 /* tp_str */ 0, 251 /* tp_getattro */ 0, 252 /* tp_setattro */ 0, 253 /* tp_as_buffer */ 0, 254 /* tp_flags */ Py_TPFLAGS_DEFAULT, 255 /* tp_doc */ "Thread-local dummy", 256 /* tp_traverse */ 0, 257 /* tp_clear */ 0, 258 /* tp_richcompare */ 0, 259 /* tp_weaklistoffset */ offsetof(localdummyobject, weakreflist) 260 }; 261 262 263 typedef struct { 264 PyObject_HEAD 265 PyObject *key; 266 PyObject *args; 267 PyObject *kw; 268 PyObject *weakreflist; /* List of weak references to self */ 269 /* A {localdummy weakref -> localdict} dict */ 270 PyObject *dummies; 271 /* The callback for weakrefs to localdummies */ 272 PyObject *wr_callback; 273 } localobject; 274 275 /* Forward declaration */ 276 static PyObject *_ldict(localobject *self); 277 static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref); 278 279 /* Create and register the dummy for the current thread. 280 Returns a borrowed reference of the corresponding local dict */ 281 static PyObject * 282 _local_create_dummy(localobject *self) 283 { 284 PyObject *tdict, *ldict = NULL, *wr = NULL; 285 localdummyobject *dummy = NULL; 286 int r; 287 288 tdict = PyThreadState_GetDict(); 289 if (tdict == NULL) { 290 PyErr_SetString(PyExc_SystemError, 291 "Couldn't get thread-state dictionary"); 292 goto err; 293 } 294 295 ldict = PyDict_New(); 296 if (ldict == NULL) 297 goto err; 298 dummy = (localdummyobject *) localdummytype.tp_alloc(&localdummytype, 0); 299 if (dummy == NULL) 300 goto err; 301 dummy->localdict = ldict; 302 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback); 303 if (wr == NULL) 304 goto err; 305 306 /* As a side-effect, this will cache the weakref's hash before the 307 dummy gets deleted */ 308 r = PyDict_SetItem(self->dummies, wr, ldict); 309 if (r < 0) 310 goto err; 311 Py_CLEAR(wr); 312 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy); 313 if (r < 0) 314 goto err; 315 Py_CLEAR(dummy); 316 317 Py_DECREF(ldict); 318 return ldict; 319 320 err: 321 Py_XDECREF(ldict); 322 Py_XDECREF(wr); 323 Py_XDECREF(dummy); 324 return NULL; 325 } 326 327 static PyObject * 328 local_new(PyTypeObject *type, PyObject *args, PyObject *kw) 329 { 330 localobject *self; 331 PyObject *wr; 332 static PyMethodDef wr_callback_def = { 333 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O 334 }; 335 336 if (type->tp_init == PyBaseObject_Type.tp_init 337 && ((args && PyObject_IsTrue(args)) 338 || (kw && PyObject_IsTrue(kw)))) { 339 PyErr_SetString(PyExc_TypeError, 340 "Initialization arguments are not supported"); 341 return NULL; 342 } 343 344 self = (localobject *)type->tp_alloc(type, 0); 345 if (self == NULL) 346 return NULL; 347 348 Py_XINCREF(args); 349 self->args = args; 350 Py_XINCREF(kw); 351 self->kw = kw; 352 self->key = PyString_FromFormat("thread.local.%p", self); 353 if (self->key == NULL) 354 goto err; 355 356 self->dummies = PyDict_New(); 357 if (self->dummies == NULL) 358 goto err; 359 360 /* We use a weak reference to self in the callback closure 361 in order to avoid spurious reference cycles */ 362 wr = PyWeakref_NewRef((PyObject *) self, NULL); 363 if (wr == NULL) 364 goto err; 365 self->wr_callback = PyCFunction_New(&wr_callback_def, wr); 366 Py_DECREF(wr); 367 if (self->wr_callback == NULL) 368 goto err; 369 370 if (_local_create_dummy(self) == NULL) 371 goto err; 372 373 return (PyObject *)self; 374 375 err: 376 Py_DECREF(self); 377 return NULL; 378 } 379 380 static int 381 local_traverse(localobject *self, visitproc visit, void *arg) 382 { 383 Py_VISIT(self->args); 384 Py_VISIT(self->kw); 385 Py_VISIT(self->dummies); 386 return 0; 387 } 388 389 static int 390 local_clear(localobject *self) 391 { 392 PyThreadState *tstate; 393 Py_CLEAR(self->args); 394 Py_CLEAR(self->kw); 395 Py_CLEAR(self->dummies); 396 Py_CLEAR(self->wr_callback); 397 /* Remove all strong references to dummies from the thread states */ 398 if (self->key 399 && (tstate = PyThreadState_Get()) 400 && tstate->interp) { 401 for(tstate = PyInterpreterState_ThreadHead(tstate->interp); 402 tstate; 403 tstate = PyThreadState_Next(tstate)) 404 if (tstate->dict && 405 PyDict_GetItem(tstate->dict, self->key)) 406 PyDict_DelItem(tstate->dict, self->key); 407 } 408 return 0; 409 } 410 411 static void 412 local_dealloc(localobject *self) 413 { 414 /* Weakrefs must be invalidated right now, otherwise they can be used 415 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */ 416 if (self->weakreflist != NULL) 417 PyObject_ClearWeakRefs((PyObject *) self); 418 419 PyObject_GC_UnTrack(self); 420 421 local_clear(self); 422 Py_XDECREF(self->key); 423 Py_TYPE(self)->tp_free((PyObject*)self); 424 } 425 426 /* Returns a borrowed reference to the local dict, creating it if necessary */ 427 static PyObject * 428 _ldict(localobject *self) 429 { 430 PyObject *tdict, *ldict, *dummy; 431 432 tdict = PyThreadState_GetDict(); 433 if (tdict == NULL) { 434 PyErr_SetString(PyExc_SystemError, 435 "Couldn't get thread-state dictionary"); 436 return NULL; 437 } 438 439 dummy = PyDict_GetItem(tdict, self->key); 440 if (dummy == NULL) { 441 ldict = _local_create_dummy(self); 442 if (ldict == NULL) 443 return NULL; 444 445 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && 446 Py_TYPE(self)->tp_init((PyObject*)self, 447 self->args, self->kw) < 0) { 448 /* we need to get rid of ldict from thread so 449 we create a new one the next time we do an attr 450 access */ 451 PyDict_DelItem(tdict, self->key); 452 return NULL; 453 } 454 } 455 else { 456 assert(Py_TYPE(dummy) == &localdummytype); 457 ldict = ((localdummyobject *) dummy)->localdict; 458 } 459 460 return ldict; 461 } 462 463 static int 464 local_setattro(localobject *self, PyObject *name, PyObject *v) 465 { 466 PyObject *ldict; 467 int r; 468 469 ldict = _ldict(self); 470 if (ldict == NULL) 471 return -1; 472 473 r = PyObject_RichCompareBool(name, str_dict, Py_EQ); 474 if (r == 1) { 475 PyErr_Format(PyExc_AttributeError, 476 "'%.50s' object attribute '__dict__' is read-only", 477 Py_TYPE(self)->tp_name); 478 return -1; 479 } 480 if (r == -1) 481 return -1; 482 483 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict); 484 } 485 486 static PyObject *local_getattro(localobject *, PyObject *); 487 488 static PyTypeObject localtype = { 489 PyVarObject_HEAD_INIT(NULL, 0) 490 /* tp_name */ "thread._local", 491 /* tp_basicsize */ sizeof(localobject), 492 /* tp_itemsize */ 0, 493 /* tp_dealloc */ (destructor)local_dealloc, 494 /* tp_print */ 0, 495 /* tp_getattr */ 0, 496 /* tp_setattr */ 0, 497 /* tp_compare */ 0, 498 /* tp_repr */ 0, 499 /* tp_as_number */ 0, 500 /* tp_as_sequence */ 0, 501 /* tp_as_mapping */ 0, 502 /* tp_hash */ 0, 503 /* tp_call */ 0, 504 /* tp_str */ 0, 505 /* tp_getattro */ (getattrofunc)local_getattro, 506 /* tp_setattro */ (setattrofunc)local_setattro, 507 /* tp_as_buffer */ 0, 508 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE 509 | Py_TPFLAGS_HAVE_GC, 510 /* tp_doc */ "Thread-local data", 511 /* tp_traverse */ (traverseproc)local_traverse, 512 /* tp_clear */ (inquiry)local_clear, 513 /* tp_richcompare */ 0, 514 /* tp_weaklistoffset */ offsetof(localobject, weakreflist), 515 /* tp_iter */ 0, 516 /* tp_iternext */ 0, 517 /* tp_methods */ 0, 518 /* tp_members */ 0, 519 /* tp_getset */ 0, 520 /* tp_base */ 0, 521 /* tp_dict */ 0, /* internal use */ 522 /* tp_descr_get */ 0, 523 /* tp_descr_set */ 0, 524 /* tp_dictoffset */ 0, 525 /* tp_init */ 0, 526 /* tp_alloc */ 0, 527 /* tp_new */ local_new, 528 /* tp_free */ 0, /* Low-level free-mem routine */ 529 /* tp_is_gc */ 0, /* For PyObject_IS_GC */ 530 }; 531 532 static PyObject * 533 local_getattro(localobject *self, PyObject *name) 534 { 535 PyObject *ldict, *value; 536 int r; 537 538 ldict = _ldict(self); 539 if (ldict == NULL) 540 return NULL; 541 542 r = PyObject_RichCompareBool(name, str_dict, Py_EQ); 543 if (r == 1) { 544 Py_INCREF(ldict); 545 return ldict; 546 } 547 if (r == -1) 548 return NULL; 549 550 if (Py_TYPE(self) != &localtype) 551 /* use generic lookup for subtypes */ 552 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict); 553 554 /* Optimization: just look in dict ourselves */ 555 value = PyDict_GetItem(ldict, name); 556 if (value == NULL) 557 /* Fall back on generic to get __class__ and __dict__ */ 558 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict); 559 560 Py_INCREF(value); 561 return value; 562 } 563 564 /* Called when a dummy is destroyed. */ 565 static PyObject * 566 _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref) 567 { 568 PyObject *obj; 569 localobject *self; 570 assert(PyWeakref_CheckRef(localweakref)); 571 obj = PyWeakref_GET_OBJECT(localweakref); 572 if (obj == Py_None) 573 Py_RETURN_NONE; 574 Py_INCREF(obj); 575 assert(PyObject_TypeCheck(obj, &localtype)); 576 /* If the thread-local object is still alive and not being cleared, 577 remove the corresponding local dict */ 578 self = (localobject *) obj; 579 if (self->dummies != NULL) { 580 PyObject *ldict; 581 ldict = PyDict_GetItem(self->dummies, dummyweakref); 582 if (ldict != NULL) { 583 PyDict_DelItem(self->dummies, dummyweakref); 584 } 585 if (PyErr_Occurred()) 586 PyErr_WriteUnraisable(obj); 587 } 588 Py_DECREF(obj); 589 Py_RETURN_NONE; 590 } 591 592 /* Module functions */ 593 594 struct bootstate { 595 PyInterpreterState *interp; 596 PyObject *func; 597 PyObject *args; 598 PyObject *keyw; 599 PyThreadState *tstate; 600 }; 601 602 static void 603 t_bootstrap(void *boot_raw) 604 { 605 struct bootstate *boot = (struct bootstate *) boot_raw; 606 PyThreadState *tstate; 607 PyObject *res; 608 609 tstate = boot->tstate; 610 tstate->thread_id = PyThread_get_thread_ident(); 611 _PyThreadState_Init(tstate); 612 PyEval_AcquireThread(tstate); 613 nb_threads++; 614 res = PyEval_CallObjectWithKeywords( 615 boot->func, boot->args, boot->keyw); 616 if (res == NULL) { 617 if (PyErr_ExceptionMatches(PyExc_SystemExit)) 618 PyErr_Clear(); 619 else { 620 PyObject *file; 621 PySys_WriteStderr( 622 "Unhandled exception in thread started by "); 623 file = PySys_GetObject("stderr"); 624 if (file) 625 PyFile_WriteObject(boot->func, file, 0); 626 else 627 PyObject_Print(boot->func, stderr, 0); 628 PySys_WriteStderr("\n"); 629 PyErr_PrintEx(0); 630 } 631 } 632 else 633 Py_DECREF(res); 634 Py_DECREF(boot->func); 635 Py_DECREF(boot->args); 636 Py_XDECREF(boot->keyw); 637 PyMem_DEL(boot_raw); 638 nb_threads--; 639 PyThreadState_Clear(tstate); 640 PyThreadState_DeleteCurrent(); 641 PyThread_exit_thread(); 642 } 643 644 static PyObject * 645 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) 646 { 647 PyObject *func, *args, *keyw = NULL; 648 struct bootstate *boot; 649 long ident; 650 651 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, 652 &func, &args, &keyw)) 653 return NULL; 654 if (!PyCallable_Check(func)) { 655 PyErr_SetString(PyExc_TypeError, 656 "first arg must be callable"); 657 return NULL; 658 } 659 if (!PyTuple_Check(args)) { 660 PyErr_SetString(PyExc_TypeError, 661 "2nd arg must be a tuple"); 662 return NULL; 663 } 664 if (keyw != NULL && !PyDict_Check(keyw)) { 665 PyErr_SetString(PyExc_TypeError, 666 "optional 3rd arg must be a dictionary"); 667 return NULL; 668 } 669 boot = PyMem_NEW(struct bootstate, 1); 670 if (boot == NULL) 671 return PyErr_NoMemory(); 672 boot->interp = PyThreadState_GET()->interp; 673 boot->func = func; 674 boot->args = args; 675 boot->keyw = keyw; 676 boot->tstate = _PyThreadState_Prealloc(boot->interp); 677 if (boot->tstate == NULL) { 678 PyMem_DEL(boot); 679 return PyErr_NoMemory(); 680 } 681 Py_INCREF(func); 682 Py_INCREF(args); 683 Py_XINCREF(keyw); 684 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ 685 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot); 686 if (ident == -1) { 687 PyErr_SetString(ThreadError, "can't start new thread"); 688 Py_DECREF(func); 689 Py_DECREF(args); 690 Py_XDECREF(keyw); 691 PyThreadState_Clear(boot->tstate); 692 PyMem_DEL(boot); 693 return NULL; 694 } 695 return PyInt_FromLong(ident); 696 } 697 698 PyDoc_STRVAR(start_new_doc, 699 "start_new_thread(function, args[, kwargs])\n\ 700 (start_new() is an obsolete synonym)\n\ 701 \n\ 702 Start a new thread and return its identifier. The thread will call the\n\ 703 function with positional arguments from the tuple args and keyword arguments\n\ 704 taken from the optional dictionary kwargs. The thread exits when the\n\ 705 function returns; the return value is ignored. The thread will also exit\n\ 706 when the function raises an unhandled exception; a stack trace will be\n\ 707 printed unless the exception is SystemExit.\n"); 708 709 static PyObject * 710 thread_PyThread_exit_thread(PyObject *self) 711 { 712 PyErr_SetNone(PyExc_SystemExit); 713 return NULL; 714 } 715 716 PyDoc_STRVAR(exit_doc, 717 "exit()\n\ 718 (PyThread_exit_thread() is an obsolete synonym)\n\ 719 \n\ 720 This is synonymous to ``raise SystemExit''. It will cause the current\n\ 721 thread to exit silently unless the exception is caught."); 722 723 static PyObject * 724 thread_PyThread_interrupt_main(PyObject * self) 725 { 726 PyErr_SetInterrupt(); 727 Py_INCREF(Py_None); 728 return Py_None; 729 } 730 731 PyDoc_STRVAR(interrupt_doc, 732 "interrupt_main()\n\ 733 \n\ 734 Raise a KeyboardInterrupt in the main thread.\n\ 735 A subthread can use this function to interrupt the main thread." 736 ); 737 738 static lockobject *newlockobject(void); 739 740 static PyObject * 741 thread_PyThread_allocate_lock(PyObject *self) 742 { 743 return (PyObject *) newlockobject(); 744 } 745 746 PyDoc_STRVAR(allocate_doc, 747 "allocate_lock() -> lock object\n\ 748 (allocate() is an obsolete synonym)\n\ 749 \n\ 750 Create a new lock object. See help(LockType) for information about locks."); 751 752 static PyObject * 753 thread_get_ident(PyObject *self) 754 { 755 long ident; 756 ident = PyThread_get_thread_ident(); 757 if (ident == -1) { 758 PyErr_SetString(ThreadError, "no current thread ident"); 759 return NULL; 760 } 761 return PyInt_FromLong(ident); 762 } 763 764 PyDoc_STRVAR(get_ident_doc, 765 "get_ident() -> integer\n\ 766 \n\ 767 Return a non-zero integer that uniquely identifies the current thread\n\ 768 amongst other threads that exist simultaneously.\n\ 769 This may be used to identify per-thread resources.\n\ 770 Even though on some platforms threads identities may appear to be\n\ 771 allocated consecutive numbers starting at 1, this behavior should not\n\ 772 be relied upon, and the number should be seen purely as a magic cookie.\n\ 773 A thread's identity may be reused for another thread after it exits."); 774 775 static PyObject * 776 thread__count(PyObject *self) 777 { 778 return PyInt_FromLong(nb_threads); 779 } 780 781 PyDoc_STRVAR(_count_doc, 782 "_count() -> integer\n\ 783 \n\ 784 \ 785 Return the number of currently running Python threads, excluding \n\ 786 the main thread. The returned number comprises all threads created\n\ 787 through `start_new_thread()` as well as `threading.Thread`, and not\n\ 788 yet finished.\n\ 789 \n\ 790 This function is meant for internal and specialized purposes only.\n\ 791 In most applications `threading.enumerate()` should be used instead."); 792 793 static PyObject * 794 thread_stack_size(PyObject *self, PyObject *args) 795 { 796 size_t old_size; 797 Py_ssize_t new_size = 0; 798 int rc; 799 800 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size)) 801 return NULL; 802 803 if (new_size < 0) { 804 PyErr_SetString(PyExc_ValueError, 805 "size must be 0 or a positive value"); 806 return NULL; 807 } 808 809 old_size = PyThread_get_stacksize(); 810 811 rc = PyThread_set_stacksize((size_t) new_size); 812 if (rc == -1) { 813 PyErr_Format(PyExc_ValueError, 814 "size not valid: %zd bytes", 815 new_size); 816 return NULL; 817 } 818 if (rc == -2) { 819 PyErr_SetString(ThreadError, 820 "setting stack size not supported"); 821 return NULL; 822 } 823 824 return PyInt_FromSsize_t((Py_ssize_t) old_size); 825 } 826 827 PyDoc_STRVAR(stack_size_doc, 828 "stack_size([size]) -> size\n\ 829 \n\ 830 Return the thread stack size used when creating new threads. The\n\ 831 optional size argument specifies the stack size (in bytes) to be used\n\ 832 for subsequently created threads, and must be 0 (use platform or\n\ 833 configured default) or a positive integer value of at least 32,768 (32k).\n\ 834 If changing the thread stack size is unsupported, a ThreadError\n\ 835 exception is raised. If the specified size is invalid, a ValueError\n\ 836 exception is raised, and the stack size is unmodified. 32k bytes\n\ 837 currently the minimum supported stack size value to guarantee\n\ 838 sufficient stack space for the interpreter itself.\n\ 839 \n\ 840 Note that some platforms may have particular restrictions on values for\n\ 841 the stack size, such as requiring a minimum stack size larger than 32kB or\n\ 842 requiring allocation in multiples of the system memory page size\n\ 843 - platform documentation should be referred to for more information\n\ 844 (4kB pages are common; using multiples of 4096 for the stack size is\n\ 845 the suggested approach in the absence of more specific information)."); 846 847 static PyMethodDef thread_methods[] = { 848 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, 849 METH_VARARGS, 850 start_new_doc}, 851 {"start_new", (PyCFunction)thread_PyThread_start_new_thread, 852 METH_VARARGS, 853 start_new_doc}, 854 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock, 855 METH_NOARGS, allocate_doc}, 856 {"allocate", (PyCFunction)thread_PyThread_allocate_lock, 857 METH_NOARGS, allocate_doc}, 858 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread, 859 METH_NOARGS, exit_doc}, 860 {"exit", (PyCFunction)thread_PyThread_exit_thread, 861 METH_NOARGS, exit_doc}, 862 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main, 863 METH_NOARGS, interrupt_doc}, 864 {"get_ident", (PyCFunction)thread_get_ident, 865 METH_NOARGS, get_ident_doc}, 866 {"_count", (PyCFunction)thread__count, 867 METH_NOARGS, _count_doc}, 868 {"stack_size", (PyCFunction)thread_stack_size, 869 METH_VARARGS, 870 stack_size_doc}, 871 {NULL, NULL} /* sentinel */ 872 }; 873 874 875 /* Initialization function */ 876 877 PyDoc_STRVAR(thread_doc, 878 "This module provides primitive operations to write multi-threaded programs.\n\ 879 The 'threading' module provides a more convenient interface."); 880 881 PyDoc_STRVAR(lock_doc, 882 "A lock object is a synchronization primitive. To create a lock,\n\ 883 call the PyThread_allocate_lock() function. Methods are:\n\ 884 \n\ 885 acquire() -- lock the lock, possibly blocking until it can be obtained\n\ 886 release() -- unlock of the lock\n\ 887 locked() -- test whether the lock is currently locked\n\ 888 \n\ 889 A lock is not owned by the thread that locked it; another thread may\n\ 890 unlock it. A thread attempting to lock a lock that it has already locked\n\ 891 will block until another thread unlocks it. Deadlocks may ensue."); 892 893 PyMODINIT_FUNC 894 initthread(void) 895 { 896 PyObject *m, *d; 897 898 /* Initialize types: */ 899 if (PyType_Ready(&localdummytype) < 0) 900 return; 901 if (PyType_Ready(&localtype) < 0) 902 return; 903 904 /* Create the module and add the functions */ 905 m = Py_InitModule3("thread", thread_methods, thread_doc); 906 if (m == NULL) 907 return; 908 909 /* Add a symbolic constant */ 910 d = PyModule_GetDict(m); 911 ThreadError = PyErr_NewException("thread.error", NULL, NULL); 912 PyDict_SetItemString(d, "error", ThreadError); 913 Locktype.tp_doc = lock_doc; 914 if (PyType_Ready(&Locktype) < 0) 915 return; 916 Py_INCREF(&Locktype); 917 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); 918 919 Py_INCREF(&localtype); 920 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) 921 return; 922 923 nb_threads = 0; 924 925 str_dict = PyString_InternFromString("__dict__"); 926 if (str_dict == NULL) 927 return; 928 929 /* Initialize the C thread library */ 930 PyThread_init_thread(); 931 } 932