1
2 /* Thread module */
3 /* Interface to Sjoerd's portable C thread library */
4
5 #include "Python.h"
6 #include "internal/pystate.h"
7 #include "structmember.h" /* offsetof */
8 #include "pythread.h"
9
10 static PyObject *ThreadError;
11 static PyObject *str_dict;
12
13 _Py_IDENTIFIER(stderr);
14
15 /* Lock objects */
16
17 typedef struct {
18 PyObject_HEAD
19 PyThread_type_lock lock_lock;
20 PyObject *in_weakreflist;
21 char locked; /* for sanity checking */
22 } lockobject;
23
24 static void
lock_dealloc(lockobject * self)25 lock_dealloc(lockobject *self)
26 {
27 if (self->in_weakreflist != NULL)
28 PyObject_ClearWeakRefs((PyObject *) self);
29 if (self->lock_lock != NULL) {
30 /* Unlock the lock so it's safe to free it */
31 if (self->locked)
32 PyThread_release_lock(self->lock_lock);
33 PyThread_free_lock(self->lock_lock);
34 }
35 PyObject_Del(self);
36 }
37
38 /* Helper to acquire an interruptible lock with a timeout. If the lock acquire
39 * is interrupted, signal handlers are run, and if they raise an exception,
40 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
41 * are returned, depending on whether the lock can be acquired within the
42 * timeout.
43 */
44 static PyLockStatus
acquire_timed(PyThread_type_lock lock,_PyTime_t timeout)45 acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
46 {
47 PyLockStatus r;
48 _PyTime_t endtime = 0;
49 _PyTime_t microseconds;
50
51 if (timeout > 0)
52 endtime = _PyTime_GetMonotonicClock() + timeout;
53
54 do {
55 microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
56
57 /* first a simple non-blocking try without releasing the GIL */
58 r = PyThread_acquire_lock_timed(lock, 0, 0);
59 if (r == PY_LOCK_FAILURE && microseconds != 0) {
60 Py_BEGIN_ALLOW_THREADS
61 r = PyThread_acquire_lock_timed(lock, microseconds, 1);
62 Py_END_ALLOW_THREADS
63 }
64
65 if (r == PY_LOCK_INTR) {
66 /* Run signal handlers if we were interrupted. Propagate
67 * exceptions from signal handlers, such as KeyboardInterrupt, by
68 * passing up PY_LOCK_INTR. */
69 if (Py_MakePendingCalls() < 0) {
70 return PY_LOCK_INTR;
71 }
72
73 /* If we're using a timeout, recompute the timeout after processing
74 * signals, since those can take time. */
75 if (timeout > 0) {
76 timeout = endtime - _PyTime_GetMonotonicClock();
77
78 /* Check for negative values, since those mean block forever.
79 */
80 if (timeout < 0) {
81 r = PY_LOCK_FAILURE;
82 }
83 }
84 }
85 } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */
86
87 return r;
88 }
89
90 static int
lock_acquire_parse_args(PyObject * args,PyObject * kwds,_PyTime_t * timeout)91 lock_acquire_parse_args(PyObject *args, PyObject *kwds,
92 _PyTime_t *timeout)
93 {
94 char *kwlist[] = {"blocking", "timeout", NULL};
95 int blocking = 1;
96 PyObject *timeout_obj = NULL;
97 const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
98
99 *timeout = unset_timeout ;
100
101 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:acquire", kwlist,
102 &blocking, &timeout_obj))
103 return -1;
104
105 if (timeout_obj
106 && _PyTime_FromSecondsObject(timeout,
107 timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
108 return -1;
109
110 if (!blocking && *timeout != unset_timeout ) {
111 PyErr_SetString(PyExc_ValueError,
112 "can't specify a timeout for a non-blocking call");
113 return -1;
114 }
115 if (*timeout < 0 && *timeout != unset_timeout) {
116 PyErr_SetString(PyExc_ValueError,
117 "timeout value must be positive");
118 return -1;
119 }
120 if (!blocking)
121 *timeout = 0;
122 else if (*timeout != unset_timeout) {
123 _PyTime_t microseconds;
124
125 microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
126 if (microseconds >= PY_TIMEOUT_MAX) {
127 PyErr_SetString(PyExc_OverflowError,
128 "timeout value is too large");
129 return -1;
130 }
131 }
132 return 0;
133 }
134
135 static PyObject *
lock_PyThread_acquire_lock(lockobject * self,PyObject * args,PyObject * kwds)136 lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
137 {
138 _PyTime_t timeout;
139 PyLockStatus r;
140
141 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
142 return NULL;
143
144 r = acquire_timed(self->lock_lock, timeout);
145 if (r == PY_LOCK_INTR) {
146 return NULL;
147 }
148
149 if (r == PY_LOCK_ACQUIRED)
150 self->locked = 1;
151 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
152 }
153
154 PyDoc_STRVAR(acquire_doc,
155 "acquire(blocking=True, timeout=-1) -> bool\n\
156 (acquire_lock() is an obsolete synonym)\n\
157 \n\
158 Lock the lock. Without argument, this blocks if the lock is already\n\
159 locked (even by the same thread), waiting for another thread to release\n\
160 the lock, and return True once the lock is acquired.\n\
161 With an argument, this will only block if the argument is true,\n\
162 and the return value reflects whether the lock is acquired.\n\
163 The blocking operation is interruptible.");
164
165 static PyObject *
lock_PyThread_release_lock(lockobject * self)166 lock_PyThread_release_lock(lockobject *self)
167 {
168 /* Sanity check: the lock must be locked */
169 if (!self->locked) {
170 PyErr_SetString(ThreadError, "release unlocked lock");
171 return NULL;
172 }
173
174 PyThread_release_lock(self->lock_lock);
175 self->locked = 0;
176 Py_RETURN_NONE;
177 }
178
179 PyDoc_STRVAR(release_doc,
180 "release()\n\
181 (release_lock() is an obsolete synonym)\n\
182 \n\
183 Release the lock, allowing another thread that is blocked waiting for\n\
184 the lock to acquire the lock. The lock must be in the locked state,\n\
185 but it needn't be locked by the same thread that unlocks it.");
186
187 static PyObject *
lock_locked_lock(lockobject * self)188 lock_locked_lock(lockobject *self)
189 {
190 return PyBool_FromLong((long)self->locked);
191 }
192
193 PyDoc_STRVAR(locked_doc,
194 "locked() -> bool\n\
195 (locked_lock() is an obsolete synonym)\n\
196 \n\
197 Return whether the lock is in the locked state.");
198
199 static PyObject *
lock_repr(lockobject * self)200 lock_repr(lockobject *self)
201 {
202 return PyUnicode_FromFormat("<%s %s object at %p>",
203 self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
204 }
205
206 static PyMethodDef lock_methods[] = {
207 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
208 METH_VARARGS | METH_KEYWORDS, acquire_doc},
209 {"acquire", (PyCFunction)lock_PyThread_acquire_lock,
210 METH_VARARGS | METH_KEYWORDS, acquire_doc},
211 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
212 METH_NOARGS, release_doc},
213 {"release", (PyCFunction)lock_PyThread_release_lock,
214 METH_NOARGS, release_doc},
215 {"locked_lock", (PyCFunction)lock_locked_lock,
216 METH_NOARGS, locked_doc},
217 {"locked", (PyCFunction)lock_locked_lock,
218 METH_NOARGS, locked_doc},
219 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock,
220 METH_VARARGS | METH_KEYWORDS, acquire_doc},
221 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
222 METH_VARARGS, release_doc},
223 {NULL, NULL} /* sentinel */
224 };
225
226 static PyTypeObject Locktype = {
227 PyVarObject_HEAD_INIT(&PyType_Type, 0)
228 "_thread.lock", /*tp_name*/
229 sizeof(lockobject), /*tp_basicsize*/
230 0, /*tp_itemsize*/
231 /* methods */
232 (destructor)lock_dealloc, /*tp_dealloc*/
233 0, /*tp_print*/
234 0, /*tp_getattr*/
235 0, /*tp_setattr*/
236 0, /*tp_reserved*/
237 (reprfunc)lock_repr, /*tp_repr*/
238 0, /*tp_as_number*/
239 0, /*tp_as_sequence*/
240 0, /*tp_as_mapping*/
241 0, /*tp_hash*/
242 0, /*tp_call*/
243 0, /*tp_str*/
244 0, /*tp_getattro*/
245 0, /*tp_setattro*/
246 0, /*tp_as_buffer*/
247 Py_TPFLAGS_DEFAULT, /*tp_flags*/
248 0, /*tp_doc*/
249 0, /*tp_traverse*/
250 0, /*tp_clear*/
251 0, /*tp_richcompare*/
252 offsetof(lockobject, in_weakreflist), /*tp_weaklistoffset*/
253 0, /*tp_iter*/
254 0, /*tp_iternext*/
255 lock_methods, /*tp_methods*/
256 };
257
258 /* Recursive lock objects */
259
260 typedef struct {
261 PyObject_HEAD
262 PyThread_type_lock rlock_lock;
263 unsigned long rlock_owner;
264 unsigned long rlock_count;
265 PyObject *in_weakreflist;
266 } rlockobject;
267
268 static void
rlock_dealloc(rlockobject * self)269 rlock_dealloc(rlockobject *self)
270 {
271 if (self->in_weakreflist != NULL)
272 PyObject_ClearWeakRefs((PyObject *) self);
273 /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
274 in rlock_new() */
275 if (self->rlock_lock != NULL) {
276 /* Unlock the lock so it's safe to free it */
277 if (self->rlock_count > 0)
278 PyThread_release_lock(self->rlock_lock);
279
280 PyThread_free_lock(self->rlock_lock);
281 }
282 Py_TYPE(self)->tp_free(self);
283 }
284
285 static PyObject *
rlock_acquire(rlockobject * self,PyObject * args,PyObject * kwds)286 rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
287 {
288 _PyTime_t timeout;
289 unsigned long tid;
290 PyLockStatus r = PY_LOCK_ACQUIRED;
291
292 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
293 return NULL;
294
295 tid = PyThread_get_thread_ident();
296 if (self->rlock_count > 0 && tid == self->rlock_owner) {
297 unsigned long count = self->rlock_count + 1;
298 if (count <= self->rlock_count) {
299 PyErr_SetString(PyExc_OverflowError,
300 "Internal lock count overflowed");
301 return NULL;
302 }
303 self->rlock_count = count;
304 Py_RETURN_TRUE;
305 }
306 r = acquire_timed(self->rlock_lock, timeout);
307 if (r == PY_LOCK_ACQUIRED) {
308 assert(self->rlock_count == 0);
309 self->rlock_owner = tid;
310 self->rlock_count = 1;
311 }
312 else if (r == PY_LOCK_INTR) {
313 return NULL;
314 }
315
316 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
317 }
318
319 PyDoc_STRVAR(rlock_acquire_doc,
320 "acquire(blocking=True) -> bool\n\
321 \n\
322 Lock the lock. `blocking` indicates whether we should wait\n\
323 for the lock to be available or not. If `blocking` is False\n\
324 and another thread holds the lock, the method will return False\n\
325 immediately. If `blocking` is True and another thread holds\n\
326 the lock, the method will wait for the lock to be released,\n\
327 take it and then return True.\n\
328 (note: the blocking operation is interruptible.)\n\
329 \n\
330 In all other cases, the method will return True immediately.\n\
331 Precisely, if the current thread already holds the lock, its\n\
332 internal counter is simply incremented. If nobody holds the lock,\n\
333 the lock is taken and its internal counter initialized to 1.");
334
335 static PyObject *
rlock_release(rlockobject * self)336 rlock_release(rlockobject *self)
337 {
338 unsigned long tid = PyThread_get_thread_ident();
339
340 if (self->rlock_count == 0 || self->rlock_owner != tid) {
341 PyErr_SetString(PyExc_RuntimeError,
342 "cannot release un-acquired lock");
343 return NULL;
344 }
345 if (--self->rlock_count == 0) {
346 self->rlock_owner = 0;
347 PyThread_release_lock(self->rlock_lock);
348 }
349 Py_RETURN_NONE;
350 }
351
352 PyDoc_STRVAR(rlock_release_doc,
353 "release()\n\
354 \n\
355 Release the lock, allowing another thread that is blocked waiting for\n\
356 the lock to acquire the lock. The lock must be in the locked state,\n\
357 and must be locked by the same thread that unlocks it; otherwise a\n\
358 `RuntimeError` is raised.\n\
359 \n\
360 Do note that if the lock was acquire()d several times in a row by the\n\
361 current thread, release() needs to be called as many times for the lock\n\
362 to be available for other threads.");
363
364 static PyObject *
rlock_acquire_restore(rlockobject * self,PyObject * args)365 rlock_acquire_restore(rlockobject *self, PyObject *args)
366 {
367 unsigned long owner;
368 unsigned long count;
369 int r = 1;
370
371 if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner))
372 return NULL;
373
374 if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
375 Py_BEGIN_ALLOW_THREADS
376 r = PyThread_acquire_lock(self->rlock_lock, 1);
377 Py_END_ALLOW_THREADS
378 }
379 if (!r) {
380 PyErr_SetString(ThreadError, "couldn't acquire lock");
381 return NULL;
382 }
383 assert(self->rlock_count == 0);
384 self->rlock_owner = owner;
385 self->rlock_count = count;
386 Py_RETURN_NONE;
387 }
388
389 PyDoc_STRVAR(rlock_acquire_restore_doc,
390 "_acquire_restore(state) -> None\n\
391 \n\
392 For internal use by `threading.Condition`.");
393
394 static PyObject *
rlock_release_save(rlockobject * self)395 rlock_release_save(rlockobject *self)
396 {
397 unsigned long owner;
398 unsigned long count;
399
400 if (self->rlock_count == 0) {
401 PyErr_SetString(PyExc_RuntimeError,
402 "cannot release un-acquired lock");
403 return NULL;
404 }
405
406 owner = self->rlock_owner;
407 count = self->rlock_count;
408 self->rlock_count = 0;
409 self->rlock_owner = 0;
410 PyThread_release_lock(self->rlock_lock);
411 return Py_BuildValue("kk", count, owner);
412 }
413
414 PyDoc_STRVAR(rlock_release_save_doc,
415 "_release_save() -> tuple\n\
416 \n\
417 For internal use by `threading.Condition`.");
418
419
420 static PyObject *
rlock_is_owned(rlockobject * self)421 rlock_is_owned(rlockobject *self)
422 {
423 unsigned long tid = PyThread_get_thread_ident();
424
425 if (self->rlock_count > 0 && self->rlock_owner == tid) {
426 Py_RETURN_TRUE;
427 }
428 Py_RETURN_FALSE;
429 }
430
431 PyDoc_STRVAR(rlock_is_owned_doc,
432 "_is_owned() -> bool\n\
433 \n\
434 For internal use by `threading.Condition`.");
435
436 static PyObject *
rlock_new(PyTypeObject * type,PyObject * args,PyObject * kwds)437 rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
438 {
439 rlockobject *self;
440
441 self = (rlockobject *) type->tp_alloc(type, 0);
442 if (self != NULL) {
443 self->in_weakreflist = NULL;
444 self->rlock_owner = 0;
445 self->rlock_count = 0;
446
447 self->rlock_lock = PyThread_allocate_lock();
448 if (self->rlock_lock == NULL) {
449 Py_DECREF(self);
450 PyErr_SetString(ThreadError, "can't allocate lock");
451 return NULL;
452 }
453 }
454
455 return (PyObject *) self;
456 }
457
458 static PyObject *
rlock_repr(rlockobject * self)459 rlock_repr(rlockobject *self)
460 {
461 return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
462 self->rlock_count ? "locked" : "unlocked",
463 Py_TYPE(self)->tp_name, self->rlock_owner,
464 self->rlock_count, self);
465 }
466
467
468 static PyMethodDef rlock_methods[] = {
469 {"acquire", (PyCFunction)rlock_acquire,
470 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
471 {"release", (PyCFunction)rlock_release,
472 METH_NOARGS, rlock_release_doc},
473 {"_is_owned", (PyCFunction)rlock_is_owned,
474 METH_NOARGS, rlock_is_owned_doc},
475 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
476 METH_VARARGS, rlock_acquire_restore_doc},
477 {"_release_save", (PyCFunction)rlock_release_save,
478 METH_NOARGS, rlock_release_save_doc},
479 {"__enter__", (PyCFunction)rlock_acquire,
480 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
481 {"__exit__", (PyCFunction)rlock_release,
482 METH_VARARGS, rlock_release_doc},
483 {NULL, NULL} /* sentinel */
484 };
485
486
487 static PyTypeObject RLocktype = {
488 PyVarObject_HEAD_INIT(&PyType_Type, 0)
489 "_thread.RLock", /*tp_name*/
490 sizeof(rlockobject), /*tp_basicsize*/
491 0, /*tp_itemsize*/
492 /* methods */
493 (destructor)rlock_dealloc, /*tp_dealloc*/
494 0, /*tp_print*/
495 0, /*tp_getattr*/
496 0, /*tp_setattr*/
497 0, /*tp_reserved*/
498 (reprfunc)rlock_repr, /*tp_repr*/
499 0, /*tp_as_number*/
500 0, /*tp_as_sequence*/
501 0, /*tp_as_mapping*/
502 0, /*tp_hash*/
503 0, /*tp_call*/
504 0, /*tp_str*/
505 0, /*tp_getattro*/
506 0, /*tp_setattro*/
507 0, /*tp_as_buffer*/
508 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
509 0, /*tp_doc*/
510 0, /*tp_traverse*/
511 0, /*tp_clear*/
512 0, /*tp_richcompare*/
513 offsetof(rlockobject, in_weakreflist), /*tp_weaklistoffset*/
514 0, /*tp_iter*/
515 0, /*tp_iternext*/
516 rlock_methods, /*tp_methods*/
517 0, /* tp_members */
518 0, /* tp_getset */
519 0, /* tp_base */
520 0, /* tp_dict */
521 0, /* tp_descr_get */
522 0, /* tp_descr_set */
523 0, /* tp_dictoffset */
524 0, /* tp_init */
525 PyType_GenericAlloc, /* tp_alloc */
526 rlock_new /* tp_new */
527 };
528
529 static lockobject *
newlockobject(void)530 newlockobject(void)
531 {
532 lockobject *self;
533 self = PyObject_New(lockobject, &Locktype);
534 if (self == NULL)
535 return NULL;
536 self->lock_lock = PyThread_allocate_lock();
537 self->locked = 0;
538 self->in_weakreflist = NULL;
539 if (self->lock_lock == NULL) {
540 Py_DECREF(self);
541 PyErr_SetString(ThreadError, "can't allocate lock");
542 return NULL;
543 }
544 return self;
545 }
546
547 /* Thread-local objects */
548
549 #include "structmember.h"
550
551 /* Quick overview:
552
553 We need to be able to reclaim reference cycles as soon as possible
554 (both when a thread is being terminated, or a thread-local object
555 becomes unreachable from user data). Constraints:
556 - it must not be possible for thread-state dicts to be involved in
557 reference cycles (otherwise the cyclic GC will refuse to consider
558 objects referenced from a reachable thread-state dict, even though
559 local_dealloc would clear them)
560 - the death of a thread-state dict must still imply destruction of the
561 corresponding local dicts in all thread-local objects.
562
563 Our implementation uses small "localdummy" objects in order to break
564 the reference chain. These trivial objects are hashable (using the
565 default scheme of identity hashing) and weakrefable.
566 Each thread-state holds a separate localdummy for each local object
567 (as a /strong reference/),
568 and each thread-local object holds a dict mapping /weak references/
569 of localdummies to local dicts.
570
571 Therefore:
572 - only the thread-state dict holds a strong reference to the dummies
573 - only the thread-local object holds a strong reference to the local dicts
574 - only outside objects (application- or library-level) hold strong
575 references to the thread-local objects
576 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
577 dummies attached to that thread are called, and destroy the corresponding
578 local dicts from thread-local objects
579 - as soon as a thread-local object is destroyed, its local dicts are
580 destroyed and its dummies are manually removed from all thread states
581 - the GC can do its work correctly when a thread-local object is dangling,
582 without any interference from the thread-state dicts
583
584 As an additional optimization, each localdummy holds a borrowed reference
585 to the corresponding localdict. This borrowed reference is only used
586 by the thread-local object which has created the localdummy, which should
587 guarantee that the localdict still exists when accessed.
588 */
589
590 typedef struct {
591 PyObject_HEAD
592 PyObject *localdict; /* Borrowed reference! */
593 PyObject *weakreflist; /* List of weak references to self */
594 } localdummyobject;
595
596 static void
localdummy_dealloc(localdummyobject * self)597 localdummy_dealloc(localdummyobject *self)
598 {
599 if (self->weakreflist != NULL)
600 PyObject_ClearWeakRefs((PyObject *) self);
601 Py_TYPE(self)->tp_free((PyObject*)self);
602 }
603
604 static PyTypeObject localdummytype = {
605 PyVarObject_HEAD_INIT(NULL, 0)
606 /* tp_name */ "_thread._localdummy",
607 /* tp_basicsize */ sizeof(localdummyobject),
608 /* tp_itemsize */ 0,
609 /* tp_dealloc */ (destructor)localdummy_dealloc,
610 /* tp_print */ 0,
611 /* tp_getattr */ 0,
612 /* tp_setattr */ 0,
613 /* tp_reserved */ 0,
614 /* tp_repr */ 0,
615 /* tp_as_number */ 0,
616 /* tp_as_sequence */ 0,
617 /* tp_as_mapping */ 0,
618 /* tp_hash */ 0,
619 /* tp_call */ 0,
620 /* tp_str */ 0,
621 /* tp_getattro */ 0,
622 /* tp_setattro */ 0,
623 /* tp_as_buffer */ 0,
624 /* tp_flags */ Py_TPFLAGS_DEFAULT,
625 /* tp_doc */ "Thread-local dummy",
626 /* tp_traverse */ 0,
627 /* tp_clear */ 0,
628 /* tp_richcompare */ 0,
629 /* tp_weaklistoffset */ offsetof(localdummyobject, weakreflist)
630 };
631
632
633 typedef struct {
634 PyObject_HEAD
635 PyObject *key;
636 PyObject *args;
637 PyObject *kw;
638 PyObject *weakreflist; /* List of weak references to self */
639 /* A {localdummy weakref -> localdict} dict */
640 PyObject *dummies;
641 /* The callback for weakrefs to localdummies */
642 PyObject *wr_callback;
643 } localobject;
644
645 /* Forward declaration */
646 static PyObject *_ldict(localobject *self);
647 static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
648
649 /* Create and register the dummy for the current thread.
650 Returns a borrowed reference of the corresponding local dict */
651 static PyObject *
_local_create_dummy(localobject * self)652 _local_create_dummy(localobject *self)
653 {
654 PyObject *tdict, *ldict = NULL, *wr = NULL;
655 localdummyobject *dummy = NULL;
656 int r;
657
658 tdict = PyThreadState_GetDict();
659 if (tdict == NULL) {
660 PyErr_SetString(PyExc_SystemError,
661 "Couldn't get thread-state dictionary");
662 goto err;
663 }
664
665 ldict = PyDict_New();
666 if (ldict == NULL)
667 goto err;
668 dummy = (localdummyobject *) localdummytype.tp_alloc(&localdummytype, 0);
669 if (dummy == NULL)
670 goto err;
671 dummy->localdict = ldict;
672 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
673 if (wr == NULL)
674 goto err;
675
676 /* As a side-effect, this will cache the weakref's hash before the
677 dummy gets deleted */
678 r = PyDict_SetItem(self->dummies, wr, ldict);
679 if (r < 0)
680 goto err;
681 Py_CLEAR(wr);
682 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
683 if (r < 0)
684 goto err;
685 Py_CLEAR(dummy);
686
687 Py_DECREF(ldict);
688 return ldict;
689
690 err:
691 Py_XDECREF(ldict);
692 Py_XDECREF(wr);
693 Py_XDECREF(dummy);
694 return NULL;
695 }
696
697 static PyObject *
local_new(PyTypeObject * type,PyObject * args,PyObject * kw)698 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
699 {
700 localobject *self;
701 PyObject *wr;
702 static PyMethodDef wr_callback_def = {
703 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
704 };
705
706 if (type->tp_init == PyBaseObject_Type.tp_init) {
707 int rc = 0;
708 if (args != NULL)
709 rc = PyObject_IsTrue(args);
710 if (rc == 0 && kw != NULL)
711 rc = PyObject_IsTrue(kw);
712 if (rc != 0) {
713 if (rc > 0)
714 PyErr_SetString(PyExc_TypeError,
715 "Initialization arguments are not supported");
716 return NULL;
717 }
718 }
719
720 self = (localobject *)type->tp_alloc(type, 0);
721 if (self == NULL)
722 return NULL;
723
724 Py_XINCREF(args);
725 self->args = args;
726 Py_XINCREF(kw);
727 self->kw = kw;
728 self->key = PyUnicode_FromFormat("thread.local.%p", self);
729 if (self->key == NULL)
730 goto err;
731
732 self->dummies = PyDict_New();
733 if (self->dummies == NULL)
734 goto err;
735
736 /* We use a weak reference to self in the callback closure
737 in order to avoid spurious reference cycles */
738 wr = PyWeakref_NewRef((PyObject *) self, NULL);
739 if (wr == NULL)
740 goto err;
741 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
742 Py_DECREF(wr);
743 if (self->wr_callback == NULL)
744 goto err;
745
746 if (_local_create_dummy(self) == NULL)
747 goto err;
748
749 return (PyObject *)self;
750
751 err:
752 Py_DECREF(self);
753 return NULL;
754 }
755
756 static int
local_traverse(localobject * self,visitproc visit,void * arg)757 local_traverse(localobject *self, visitproc visit, void *arg)
758 {
759 Py_VISIT(self->args);
760 Py_VISIT(self->kw);
761 Py_VISIT(self->dummies);
762 return 0;
763 }
764
765 static int
local_clear(localobject * self)766 local_clear(localobject *self)
767 {
768 PyThreadState *tstate;
769 Py_CLEAR(self->args);
770 Py_CLEAR(self->kw);
771 Py_CLEAR(self->dummies);
772 Py_CLEAR(self->wr_callback);
773 /* Remove all strong references to dummies from the thread states */
774 if (self->key
775 && (tstate = PyThreadState_Get())
776 && tstate->interp) {
777 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
778 tstate;
779 tstate = PyThreadState_Next(tstate))
780 if (tstate->dict && PyDict_GetItem(tstate->dict, self->key)) {
781 if (PyDict_DelItem(tstate->dict, self->key)) {
782 PyErr_Clear();
783 }
784 }
785 }
786 return 0;
787 }
788
789 static void
local_dealloc(localobject * self)790 local_dealloc(localobject *self)
791 {
792 /* Weakrefs must be invalidated right now, otherwise they can be used
793 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
794 if (self->weakreflist != NULL)
795 PyObject_ClearWeakRefs((PyObject *) self);
796
797 PyObject_GC_UnTrack(self);
798
799 local_clear(self);
800 Py_XDECREF(self->key);
801 Py_TYPE(self)->tp_free((PyObject*)self);
802 }
803
804 /* Returns a borrowed reference to the local dict, creating it if necessary */
805 static PyObject *
_ldict(localobject * self)806 _ldict(localobject *self)
807 {
808 PyObject *tdict, *ldict, *dummy;
809
810 tdict = PyThreadState_GetDict();
811 if (tdict == NULL) {
812 PyErr_SetString(PyExc_SystemError,
813 "Couldn't get thread-state dictionary");
814 return NULL;
815 }
816
817 dummy = PyDict_GetItem(tdict, self->key);
818 if (dummy == NULL) {
819 ldict = _local_create_dummy(self);
820 if (ldict == NULL)
821 return NULL;
822
823 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
824 Py_TYPE(self)->tp_init((PyObject*)self,
825 self->args, self->kw) < 0) {
826 /* we need to get rid of ldict from thread so
827 we create a new one the next time we do an attr
828 access */
829 PyDict_DelItem(tdict, self->key);
830 return NULL;
831 }
832 }
833 else {
834 assert(Py_TYPE(dummy) == &localdummytype);
835 ldict = ((localdummyobject *) dummy)->localdict;
836 }
837
838 return ldict;
839 }
840
841 static int
local_setattro(localobject * self,PyObject * name,PyObject * v)842 local_setattro(localobject *self, PyObject *name, PyObject *v)
843 {
844 PyObject *ldict;
845 int r;
846
847 ldict = _ldict(self);
848 if (ldict == NULL)
849 return -1;
850
851 r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
852 if (r == 1) {
853 PyErr_Format(PyExc_AttributeError,
854 "'%.50s' object attribute '%U' is read-only",
855 Py_TYPE(self)->tp_name, name);
856 return -1;
857 }
858 if (r == -1)
859 return -1;
860
861 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
862 }
863
864 static PyObject *local_getattro(localobject *, PyObject *);
865
866 static PyTypeObject localtype = {
867 PyVarObject_HEAD_INIT(NULL, 0)
868 /* tp_name */ "_thread._local",
869 /* tp_basicsize */ sizeof(localobject),
870 /* tp_itemsize */ 0,
871 /* tp_dealloc */ (destructor)local_dealloc,
872 /* tp_print */ 0,
873 /* tp_getattr */ 0,
874 /* tp_setattr */ 0,
875 /* tp_reserved */ 0,
876 /* tp_repr */ 0,
877 /* tp_as_number */ 0,
878 /* tp_as_sequence */ 0,
879 /* tp_as_mapping */ 0,
880 /* tp_hash */ 0,
881 /* tp_call */ 0,
882 /* tp_str */ 0,
883 /* tp_getattro */ (getattrofunc)local_getattro,
884 /* tp_setattro */ (setattrofunc)local_setattro,
885 /* tp_as_buffer */ 0,
886 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
887 | Py_TPFLAGS_HAVE_GC,
888 /* tp_doc */ "Thread-local data",
889 /* tp_traverse */ (traverseproc)local_traverse,
890 /* tp_clear */ (inquiry)local_clear,
891 /* tp_richcompare */ 0,
892 /* tp_weaklistoffset */ offsetof(localobject, weakreflist),
893 /* tp_iter */ 0,
894 /* tp_iternext */ 0,
895 /* tp_methods */ 0,
896 /* tp_members */ 0,
897 /* tp_getset */ 0,
898 /* tp_base */ 0,
899 /* tp_dict */ 0, /* internal use */
900 /* tp_descr_get */ 0,
901 /* tp_descr_set */ 0,
902 /* tp_dictoffset */ 0,
903 /* tp_init */ 0,
904 /* tp_alloc */ 0,
905 /* tp_new */ local_new,
906 /* tp_free */ 0, /* Low-level free-mem routine */
907 /* tp_is_gc */ 0, /* For PyObject_IS_GC */
908 };
909
910 static PyObject *
local_getattro(localobject * self,PyObject * name)911 local_getattro(localobject *self, PyObject *name)
912 {
913 PyObject *ldict, *value;
914 int r;
915
916 ldict = _ldict(self);
917 if (ldict == NULL)
918 return NULL;
919
920 r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
921 if (r == 1) {
922 Py_INCREF(ldict);
923 return ldict;
924 }
925 if (r == -1)
926 return NULL;
927
928 if (Py_TYPE(self) != &localtype)
929 /* use generic lookup for subtypes */
930 return _PyObject_GenericGetAttrWithDict(
931 (PyObject *)self, name, ldict, 0);
932
933 /* Optimization: just look in dict ourselves */
934 value = PyDict_GetItem(ldict, name);
935 if (value == NULL)
936 /* Fall back on generic to get __class__ and __dict__ */
937 return _PyObject_GenericGetAttrWithDict(
938 (PyObject *)self, name, ldict, 0);
939
940 Py_INCREF(value);
941 return value;
942 }
943
944 /* Called when a dummy is destroyed. */
945 static PyObject *
_localdummy_destroyed(PyObject * localweakref,PyObject * dummyweakref)946 _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
947 {
948 PyObject *obj;
949 localobject *self;
950 assert(PyWeakref_CheckRef(localweakref));
951 obj = PyWeakref_GET_OBJECT(localweakref);
952 if (obj == Py_None)
953 Py_RETURN_NONE;
954 Py_INCREF(obj);
955 assert(PyObject_TypeCheck(obj, &localtype));
956 /* If the thread-local object is still alive and not being cleared,
957 remove the corresponding local dict */
958 self = (localobject *) obj;
959 if (self->dummies != NULL) {
960 PyObject *ldict;
961 ldict = PyDict_GetItem(self->dummies, dummyweakref);
962 if (ldict != NULL) {
963 PyDict_DelItem(self->dummies, dummyweakref);
964 }
965 if (PyErr_Occurred())
966 PyErr_WriteUnraisable(obj);
967 }
968 Py_DECREF(obj);
969 Py_RETURN_NONE;
970 }
971
972 /* Module functions */
973
974 struct bootstate {
975 PyInterpreterState *interp;
976 PyObject *func;
977 PyObject *args;
978 PyObject *keyw;
979 PyThreadState *tstate;
980 };
981
982 static void
t_bootstrap(void * boot_raw)983 t_bootstrap(void *boot_raw)
984 {
985 struct bootstate *boot = (struct bootstate *) boot_raw;
986 PyThreadState *tstate;
987 PyObject *res;
988
989 tstate = boot->tstate;
990 tstate->thread_id = PyThread_get_thread_ident();
991 _PyThreadState_Init(tstate);
992 PyEval_AcquireThread(tstate);
993 tstate->interp->num_threads++;
994 res = PyObject_Call(boot->func, boot->args, boot->keyw);
995 if (res == NULL) {
996 if (PyErr_ExceptionMatches(PyExc_SystemExit))
997 PyErr_Clear();
998 else {
999 PyObject *file;
1000 PyObject *exc, *value, *tb;
1001 PySys_WriteStderr(
1002 "Unhandled exception in thread started by ");
1003 PyErr_Fetch(&exc, &value, &tb);
1004 file = _PySys_GetObjectId(&PyId_stderr);
1005 if (file != NULL && file != Py_None)
1006 PyFile_WriteObject(boot->func, file, 0);
1007 else
1008 PyObject_Print(boot->func, stderr, 0);
1009 PySys_WriteStderr("\n");
1010 PyErr_Restore(exc, value, tb);
1011 PyErr_PrintEx(0);
1012 }
1013 }
1014 else
1015 Py_DECREF(res);
1016 Py_DECREF(boot->func);
1017 Py_DECREF(boot->args);
1018 Py_XDECREF(boot->keyw);
1019 PyMem_DEL(boot_raw);
1020 tstate->interp->num_threads--;
1021 PyThreadState_Clear(tstate);
1022 PyThreadState_DeleteCurrent();
1023 PyThread_exit_thread();
1024 }
1025
1026 static PyObject *
thread_PyThread_start_new_thread(PyObject * self,PyObject * fargs)1027 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
1028 {
1029 PyObject *func, *args, *keyw = NULL;
1030 struct bootstate *boot;
1031 unsigned long ident;
1032
1033 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1034 &func, &args, &keyw))
1035 return NULL;
1036 if (!PyCallable_Check(func)) {
1037 PyErr_SetString(PyExc_TypeError,
1038 "first arg must be callable");
1039 return NULL;
1040 }
1041 if (!PyTuple_Check(args)) {
1042 PyErr_SetString(PyExc_TypeError,
1043 "2nd arg must be a tuple");
1044 return NULL;
1045 }
1046 if (keyw != NULL && !PyDict_Check(keyw)) {
1047 PyErr_SetString(PyExc_TypeError,
1048 "optional 3rd arg must be a dictionary");
1049 return NULL;
1050 }
1051 boot = PyMem_NEW(struct bootstate, 1);
1052 if (boot == NULL)
1053 return PyErr_NoMemory();
1054 boot->interp = PyThreadState_GET()->interp;
1055 boot->func = func;
1056 boot->args = args;
1057 boot->keyw = keyw;
1058 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1059 if (boot->tstate == NULL) {
1060 PyMem_DEL(boot);
1061 return PyErr_NoMemory();
1062 }
1063 Py_INCREF(func);
1064 Py_INCREF(args);
1065 Py_XINCREF(keyw);
1066 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
1067 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
1068 if (ident == PYTHREAD_INVALID_THREAD_ID) {
1069 PyErr_SetString(ThreadError, "can't start new thread");
1070 Py_DECREF(func);
1071 Py_DECREF(args);
1072 Py_XDECREF(keyw);
1073 PyThreadState_Clear(boot->tstate);
1074 PyMem_DEL(boot);
1075 return NULL;
1076 }
1077 return PyLong_FromUnsignedLong(ident);
1078 }
1079
1080 PyDoc_STRVAR(start_new_doc,
1081 "start_new_thread(function, args[, kwargs])\n\
1082 (start_new() is an obsolete synonym)\n\
1083 \n\
1084 Start a new thread and return its identifier. The thread will call the\n\
1085 function with positional arguments from the tuple args and keyword arguments\n\
1086 taken from the optional dictionary kwargs. The thread exits when the\n\
1087 function returns; the return value is ignored. The thread will also exit\n\
1088 when the function raises an unhandled exception; a stack trace will be\n\
1089 printed unless the exception is SystemExit.\n");
1090
1091 static PyObject *
thread_PyThread_exit_thread(PyObject * self)1092 thread_PyThread_exit_thread(PyObject *self)
1093 {
1094 PyErr_SetNone(PyExc_SystemExit);
1095 return NULL;
1096 }
1097
1098 PyDoc_STRVAR(exit_doc,
1099 "exit()\n\
1100 (exit_thread() is an obsolete synonym)\n\
1101 \n\
1102 This is synonymous to ``raise SystemExit''. It will cause the current\n\
1103 thread to exit silently unless the exception is caught.");
1104
1105 static PyObject *
thread_PyThread_interrupt_main(PyObject * self)1106 thread_PyThread_interrupt_main(PyObject * self)
1107 {
1108 PyErr_SetInterrupt();
1109 Py_RETURN_NONE;
1110 }
1111
1112 PyDoc_STRVAR(interrupt_doc,
1113 "interrupt_main()\n\
1114 \n\
1115 Raise a KeyboardInterrupt in the main thread.\n\
1116 A subthread can use this function to interrupt the main thread."
1117 );
1118
1119 static lockobject *newlockobject(void);
1120
1121 static PyObject *
thread_PyThread_allocate_lock(PyObject * self)1122 thread_PyThread_allocate_lock(PyObject *self)
1123 {
1124 return (PyObject *) newlockobject();
1125 }
1126
1127 PyDoc_STRVAR(allocate_doc,
1128 "allocate_lock() -> lock object\n\
1129 (allocate() is an obsolete synonym)\n\
1130 \n\
1131 Create a new lock object. See help(type(threading.Lock())) for\n\
1132 information about locks.");
1133
1134 static PyObject *
thread_get_ident(PyObject * self)1135 thread_get_ident(PyObject *self)
1136 {
1137 unsigned long ident = PyThread_get_thread_ident();
1138 if (ident == PYTHREAD_INVALID_THREAD_ID) {
1139 PyErr_SetString(ThreadError, "no current thread ident");
1140 return NULL;
1141 }
1142 return PyLong_FromUnsignedLong(ident);
1143 }
1144
1145 PyDoc_STRVAR(get_ident_doc,
1146 "get_ident() -> integer\n\
1147 \n\
1148 Return a non-zero integer that uniquely identifies the current thread\n\
1149 amongst other threads that exist simultaneously.\n\
1150 This may be used to identify per-thread resources.\n\
1151 Even though on some platforms threads identities may appear to be\n\
1152 allocated consecutive numbers starting at 1, this behavior should not\n\
1153 be relied upon, and the number should be seen purely as a magic cookie.\n\
1154 A thread's identity may be reused for another thread after it exits.");
1155
1156 static PyObject *
thread__count(PyObject * self)1157 thread__count(PyObject *self)
1158 {
1159 PyThreadState *tstate = PyThreadState_Get();
1160 return PyLong_FromLong(tstate->interp->num_threads);
1161 }
1162
1163 PyDoc_STRVAR(_count_doc,
1164 "_count() -> integer\n\
1165 \n\
1166 \
1167 Return the number of currently running Python threads, excluding \n\
1168 the main thread. The returned number comprises all threads created\n\
1169 through `start_new_thread()` as well as `threading.Thread`, and not\n\
1170 yet finished.\n\
1171 \n\
1172 This function is meant for internal and specialized purposes only.\n\
1173 In most applications `threading.enumerate()` should be used instead.");
1174
1175 static void
release_sentinel(void * wr)1176 release_sentinel(void *wr)
1177 {
1178 /* Tricky: this function is called when the current thread state
1179 is being deleted. Therefore, only simple C code can safely
1180 execute here. */
1181 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1182 lockobject *lock;
1183 if (obj != Py_None) {
1184 assert(Py_TYPE(obj) == &Locktype);
1185 lock = (lockobject *) obj;
1186 if (lock->locked) {
1187 PyThread_release_lock(lock->lock_lock);
1188 lock->locked = 0;
1189 }
1190 }
1191 /* Deallocating a weakref with a NULL callback only calls
1192 PyObject_GC_Del(), which can't call any Python code. */
1193 Py_DECREF(wr);
1194 }
1195
1196 static PyObject *
thread__set_sentinel(PyObject * self)1197 thread__set_sentinel(PyObject *self)
1198 {
1199 PyObject *wr;
1200 PyThreadState *tstate = PyThreadState_Get();
1201 lockobject *lock;
1202
1203 if (tstate->on_delete_data != NULL) {
1204 /* We must support the re-creation of the lock from a
1205 fork()ed child. */
1206 assert(tstate->on_delete == &release_sentinel);
1207 wr = (PyObject *) tstate->on_delete_data;
1208 tstate->on_delete = NULL;
1209 tstate->on_delete_data = NULL;
1210 Py_DECREF(wr);
1211 }
1212 lock = newlockobject();
1213 if (lock == NULL)
1214 return NULL;
1215 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1216 hangs to the thread state. */
1217 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1218 if (wr == NULL) {
1219 Py_DECREF(lock);
1220 return NULL;
1221 }
1222 tstate->on_delete_data = (void *) wr;
1223 tstate->on_delete = &release_sentinel;
1224 return (PyObject *) lock;
1225 }
1226
1227 PyDoc_STRVAR(_set_sentinel_doc,
1228 "_set_sentinel() -> lock\n\
1229 \n\
1230 Set a sentinel lock that will be released when the current thread\n\
1231 state is finalized (after it is untied from the interpreter).\n\
1232 \n\
1233 This is a private API for the threading module.");
1234
1235 static PyObject *
thread_stack_size(PyObject * self,PyObject * args)1236 thread_stack_size(PyObject *self, PyObject *args)
1237 {
1238 size_t old_size;
1239 Py_ssize_t new_size = 0;
1240 int rc;
1241
1242 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1243 return NULL;
1244
1245 if (new_size < 0) {
1246 PyErr_SetString(PyExc_ValueError,
1247 "size must be 0 or a positive value");
1248 return NULL;
1249 }
1250
1251 old_size = PyThread_get_stacksize();
1252
1253 rc = PyThread_set_stacksize((size_t) new_size);
1254 if (rc == -1) {
1255 PyErr_Format(PyExc_ValueError,
1256 "size not valid: %zd bytes",
1257 new_size);
1258 return NULL;
1259 }
1260 if (rc == -2) {
1261 PyErr_SetString(ThreadError,
1262 "setting stack size not supported");
1263 return NULL;
1264 }
1265
1266 return PyLong_FromSsize_t((Py_ssize_t) old_size);
1267 }
1268
1269 PyDoc_STRVAR(stack_size_doc,
1270 "stack_size([size]) -> size\n\
1271 \n\
1272 Return the thread stack size used when creating new threads. The\n\
1273 optional size argument specifies the stack size (in bytes) to be used\n\
1274 for subsequently created threads, and must be 0 (use platform or\n\
1275 configured default) or a positive integer value of at least 32,768 (32k).\n\
1276 If changing the thread stack size is unsupported, a ThreadError\n\
1277 exception is raised. If the specified size is invalid, a ValueError\n\
1278 exception is raised, and the stack size is unmodified. 32k bytes\n\
1279 currently the minimum supported stack size value to guarantee\n\
1280 sufficient stack space for the interpreter itself.\n\
1281 \n\
1282 Note that some platforms may have particular restrictions on values for\n\
1283 the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
1284 requiring allocation in multiples of the system memory page size\n\
1285 - platform documentation should be referred to for more information\n\
1286 (4 KiB pages are common; using multiples of 4096 for the stack size is\n\
1287 the suggested approach in the absence of more specific information).");
1288
1289 static PyMethodDef thread_methods[] = {
1290 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
1291 METH_VARARGS, start_new_doc},
1292 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
1293 METH_VARARGS, start_new_doc},
1294 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
1295 METH_NOARGS, allocate_doc},
1296 {"allocate", (PyCFunction)thread_PyThread_allocate_lock,
1297 METH_NOARGS, allocate_doc},
1298 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread,
1299 METH_NOARGS, exit_doc},
1300 {"exit", (PyCFunction)thread_PyThread_exit_thread,
1301 METH_NOARGS, exit_doc},
1302 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1303 METH_NOARGS, interrupt_doc},
1304 {"get_ident", (PyCFunction)thread_get_ident,
1305 METH_NOARGS, get_ident_doc},
1306 {"_count", (PyCFunction)thread__count,
1307 METH_NOARGS, _count_doc},
1308 {"stack_size", (PyCFunction)thread_stack_size,
1309 METH_VARARGS, stack_size_doc},
1310 {"_set_sentinel", (PyCFunction)thread__set_sentinel,
1311 METH_NOARGS, _set_sentinel_doc},
1312 {NULL, NULL} /* sentinel */
1313 };
1314
1315
1316 /* Initialization function */
1317
1318 PyDoc_STRVAR(thread_doc,
1319 "This module provides primitive operations to write multi-threaded programs.\n\
1320 The 'threading' module provides a more convenient interface.");
1321
1322 PyDoc_STRVAR(lock_doc,
1323 "A lock object is a synchronization primitive. To create a lock,\n\
1324 call threading.Lock(). Methods are:\n\
1325 \n\
1326 acquire() -- lock the lock, possibly blocking until it can be obtained\n\
1327 release() -- unlock of the lock\n\
1328 locked() -- test whether the lock is currently locked\n\
1329 \n\
1330 A lock is not owned by the thread that locked it; another thread may\n\
1331 unlock it. A thread attempting to lock a lock that it has already locked\n\
1332 will block until another thread unlocks it. Deadlocks may ensue.");
1333
1334 static struct PyModuleDef threadmodule = {
1335 PyModuleDef_HEAD_INIT,
1336 "_thread",
1337 thread_doc,
1338 -1,
1339 thread_methods,
1340 NULL,
1341 NULL,
1342 NULL,
1343 NULL
1344 };
1345
1346
1347 PyMODINIT_FUNC
PyInit__thread(void)1348 PyInit__thread(void)
1349 {
1350 PyObject *m, *d, *v;
1351 double time_max;
1352 double timeout_max;
1353 PyThreadState *tstate = PyThreadState_Get();
1354
1355 /* Initialize types: */
1356 if (PyType_Ready(&localdummytype) < 0)
1357 return NULL;
1358 if (PyType_Ready(&localtype) < 0)
1359 return NULL;
1360 if (PyType_Ready(&Locktype) < 0)
1361 return NULL;
1362 if (PyType_Ready(&RLocktype) < 0)
1363 return NULL;
1364
1365 /* Create the module and add the functions */
1366 m = PyModule_Create(&threadmodule);
1367 if (m == NULL)
1368 return NULL;
1369
1370 timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6;
1371 time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1372 timeout_max = Py_MIN(timeout_max, time_max);
1373 /* Round towards minus infinity */
1374 timeout_max = floor(timeout_max);
1375
1376 v = PyFloat_FromDouble(timeout_max);
1377 if (!v)
1378 return NULL;
1379 if (PyModule_AddObject(m, "TIMEOUT_MAX", v) < 0)
1380 return NULL;
1381
1382 /* Add a symbolic constant */
1383 d = PyModule_GetDict(m);
1384 ThreadError = PyExc_RuntimeError;
1385 Py_INCREF(ThreadError);
1386
1387 PyDict_SetItemString(d, "error", ThreadError);
1388 Locktype.tp_doc = lock_doc;
1389 Py_INCREF(&Locktype);
1390 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
1391
1392 Py_INCREF(&RLocktype);
1393 if (PyModule_AddObject(m, "RLock", (PyObject *)&RLocktype) < 0)
1394 return NULL;
1395
1396 Py_INCREF(&localtype);
1397 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
1398 return NULL;
1399
1400 tstate->interp->num_threads = 0;
1401
1402 str_dict = PyUnicode_InternFromString("__dict__");
1403 if (str_dict == NULL)
1404 return NULL;
1405
1406 /* Initialize the C thread library */
1407 PyThread_init_thread();
1408 return m;
1409 }
1410