blob: 14ed55e31b6e26874c02935f68d310e0c05df9c3 [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001
2/* Thread module */
3/* Interface to Sjoerd's portable C thread library */
4
Barry Warsawd0c10421996-12-17 00:05:22 +00005#include "Python.h"
Benjamin Petersonbec4d572009-10-10 01:16:07 +00006#include "structmember.h" /* offsetof */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00007
Guido van Rossumb6775db1994-08-01 11:34:53 +00008#ifndef WITH_THREAD
Guido van Rossuma027efa1997-05-05 20:56:21 +00009#error "Error! The rest of Python is not compiled with thread support."
Neal Norwitz884baa12002-09-05 21:31:04 +000010#error "Rerun configure, adding a --with-threads option."
Guido van Rossuma027efa1997-05-05 20:56:21 +000011#error "Then run `make clean' followed by `make'."
Guido van Rossumb6775db1994-08-01 11:34:53 +000012#endif
13
Guido van Rossum49b56061998-10-01 20:42:43 +000014#include "pythread.h"
Guido van Rossum1984f1e1992-08-04 12:41:02 +000015
Barry Warsawd0c10421996-12-17 00:05:22 +000016static PyObject *ThreadError;
Antoine Pitrou65c9c642009-10-30 17:25:12 +000017static long nb_threads = 0;
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +000018static PyObject *str_dict;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000019
20/* Lock objects */
21
22typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000023 PyObject_HEAD
24 PyThread_type_lock lock_lock;
25 PyObject *in_weakreflist;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000026} lockobject;
27
Guido van Rossum1984f1e1992-08-04 12:41:02 +000028static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +000029lock_dealloc(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000030{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000031 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);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000041}
42
Antoine Pitrou810023d2010-12-15 22:59:16 +000043/* Helper to acquire an interruptible lock with a timeout. If the lock acquire
44 * is interrupted, signal handlers are run, and if they raise an exception,
45 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
46 * are returned, depending on whether the lock can be acquired withing the
47 * timeout.
48 */
49static PyLockStatus
50acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
51{
52 PyLockStatus r;
53 _PyTime_timeval curtime;
54 _PyTime_timeval endtime;
55
Brett Cannonb94767f2011-02-22 20:15:44 +000056
57 _PyTime_gettimeofday(&endtime);
Antoine Pitrou810023d2010-12-15 22:59:16 +000058 if (microseconds > 0) {
Antoine Pitrou810023d2010-12-15 22:59:16 +000059 endtime.tv_sec += microseconds / (1000 * 1000);
60 endtime.tv_usec += microseconds % (1000 * 1000);
61 }
62
63
64 do {
65 Py_BEGIN_ALLOW_THREADS
66 r = PyThread_acquire_lock_timed(lock, microseconds, 1);
67 Py_END_ALLOW_THREADS
68
69 if (r == PY_LOCK_INTR) {
70 /* Run signal handlers if we were interrupted. Propagate
71 * exceptions from signal handlers, such as KeyboardInterrupt, by
72 * passing up PY_LOCK_INTR. */
73 if (Py_MakePendingCalls() < 0) {
74 return PY_LOCK_INTR;
75 }
76
77 /* If we're using a timeout, recompute the timeout after processing
78 * signals, since those can take time. */
79 if (microseconds >= 0) {
80 _PyTime_gettimeofday(&curtime);
81 microseconds = ((endtime.tv_sec - curtime.tv_sec) * 1000000 +
82 (endtime.tv_usec - curtime.tv_usec));
83
84 /* Check for negative values, since those mean block forever.
85 */
86 if (microseconds <= 0) {
87 r = PY_LOCK_FAILURE;
88 }
89 }
90 }
91 } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */
92
93 return r;
94}
95
Barry Warsawd0c10421996-12-17 00:05:22 +000096static PyObject *
Antoine Pitrou7c3e5772010-04-14 15:44:10 +000097lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000098{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 char *kwlist[] = {"blocking", "timeout", NULL};
100 int blocking = 1;
101 double timeout = -1;
102 PY_TIMEOUT_T microseconds;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000103 PyLockStatus r;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|id:acquire", kwlist,
106 &blocking, &timeout))
107 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 if (!blocking && timeout != -1) {
110 PyErr_SetString(PyExc_ValueError, "can't specify a timeout "
111 "for a non-blocking call");
112 return NULL;
113 }
114 if (timeout < 0 && timeout != -1) {
115 PyErr_SetString(PyExc_ValueError, "timeout value must be "
116 "strictly positive");
117 return NULL;
118 }
119 if (!blocking)
120 microseconds = 0;
121 else if (timeout == -1)
122 microseconds = -1;
123 else {
124 timeout *= 1e6;
125 if (timeout >= (double) PY_TIMEOUT_MAX) {
126 PyErr_SetString(PyExc_OverflowError,
127 "timeout value is too large");
128 return NULL;
129 }
130 microseconds = (PY_TIMEOUT_T) timeout;
131 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000132
Antoine Pitrou810023d2010-12-15 22:59:16 +0000133 r = acquire_timed(self->lock_lock, microseconds);
134 if (r == PY_LOCK_INTR) {
135 return NULL;
136 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000137
Antoine Pitrou810023d2010-12-15 22:59:16 +0000138 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000139}
140
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000141PyDoc_STRVAR(acquire_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000142"acquire([wait]) -> None or bool\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000143(acquire_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000144\n\
145Lock the lock. Without argument, this blocks if the lock is already\n\
146locked (even by the same thread), waiting for another thread to release\n\
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000147the lock, and return None once the lock is acquired.\n\
148With an argument, this will only block if the argument is true,\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000149and the return value reflects whether the lock is acquired.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000150The blocking operation is interruptible.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000151
Barry Warsawd0c10421996-12-17 00:05:22 +0000152static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000153lock_PyThread_release_lock(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000154{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 /* Sanity check: the lock must be locked */
156 if (PyThread_acquire_lock(self->lock_lock, 0)) {
157 PyThread_release_lock(self->lock_lock);
158 PyErr_SetString(ThreadError, "release unlocked lock");
159 return NULL;
160 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 PyThread_release_lock(self->lock_lock);
163 Py_INCREF(Py_None);
164 return Py_None;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000165}
166
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000167PyDoc_STRVAR(release_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000168"release()\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000169(release_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000170\n\
171Release the lock, allowing another thread that is blocked waiting for\n\
172the lock to acquire the lock. The lock must be in the locked state,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000173but it needn't be locked by the same thread that unlocks it.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000174
Barry Warsawd0c10421996-12-17 00:05:22 +0000175static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000176lock_locked_lock(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000177{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000178 if (PyThread_acquire_lock(self->lock_lock, 0)) {
179 PyThread_release_lock(self->lock_lock);
180 return PyBool_FromLong(0L);
181 }
182 return PyBool_FromLong(1L);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000183}
184
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000185PyDoc_STRVAR(locked_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000186"locked() -> bool\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000187(locked_lock() is an obsolete synonym)\n\
188\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000189Return whether the lock is in the locked state.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000190
Barry Warsawd0c10421996-12-17 00:05:22 +0000191static PyMethodDef lock_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
193 METH_VARARGS | METH_KEYWORDS, acquire_doc},
194 {"acquire", (PyCFunction)lock_PyThread_acquire_lock,
195 METH_VARARGS | METH_KEYWORDS, acquire_doc},
196 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
197 METH_NOARGS, release_doc},
198 {"release", (PyCFunction)lock_PyThread_release_lock,
199 METH_NOARGS, release_doc},
200 {"locked_lock", (PyCFunction)lock_locked_lock,
201 METH_NOARGS, locked_doc},
202 {"locked", (PyCFunction)lock_locked_lock,
203 METH_NOARGS, locked_doc},
204 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock,
205 METH_VARARGS | METH_KEYWORDS, acquire_doc},
206 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
207 METH_VARARGS, release_doc},
208 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000209};
210
Barry Warsawd0c10421996-12-17 00:05:22 +0000211static PyTypeObject Locktype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 PyVarObject_HEAD_INIT(&PyType_Type, 0)
213 "_thread.lock", /*tp_name*/
214 sizeof(lockobject), /*tp_size*/
215 0, /*tp_itemsize*/
216 /* methods */
217 (destructor)lock_dealloc, /*tp_dealloc*/
218 0, /*tp_print*/
219 0, /*tp_getattr*/
220 0, /*tp_setattr*/
221 0, /*tp_reserved*/
222 0, /*tp_repr*/
223 0, /*tp_as_number*/
224 0, /*tp_as_sequence*/
225 0, /*tp_as_mapping*/
226 0, /*tp_hash*/
227 0, /*tp_call*/
228 0, /*tp_str*/
229 0, /*tp_getattro*/
230 0, /*tp_setattro*/
231 0, /*tp_as_buffer*/
232 Py_TPFLAGS_DEFAULT, /*tp_flags*/
233 0, /*tp_doc*/
234 0, /*tp_traverse*/
235 0, /*tp_clear*/
236 0, /*tp_richcompare*/
237 offsetof(lockobject, in_weakreflist), /*tp_weaklistoffset*/
238 0, /*tp_iter*/
239 0, /*tp_iternext*/
240 lock_methods, /*tp_methods*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000241};
242
Antoine Pitrou434736a2009-11-10 18:46:01 +0000243/* Recursive lock objects */
244
245typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000246 PyObject_HEAD
247 PyThread_type_lock rlock_lock;
248 long rlock_owner;
249 unsigned long rlock_count;
250 PyObject *in_weakreflist;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000251} rlockobject;
252
253static void
254rlock_dealloc(rlockobject *self)
255{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 assert(self->rlock_lock);
257 if (self->in_weakreflist != NULL)
258 PyObject_ClearWeakRefs((PyObject *) self);
259 /* Unlock the lock so it's safe to free it */
260 if (self->rlock_count > 0)
261 PyThread_release_lock(self->rlock_lock);
262
263 PyThread_free_lock(self->rlock_lock);
264 Py_TYPE(self)->tp_free(self);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000265}
266
267static PyObject *
268rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
269{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 char *kwlist[] = {"blocking", "timeout", NULL};
271 int blocking = 1;
272 double timeout = -1;
273 PY_TIMEOUT_T microseconds;
274 long tid;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000275 PyLockStatus r = PY_LOCK_ACQUIRED;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000277 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|id:acquire", kwlist,
278 &blocking, &timeout))
279 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000280
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281 if (!blocking && timeout != -1) {
282 PyErr_SetString(PyExc_ValueError, "can't specify a timeout "
283 "for a non-blocking call");
284 return NULL;
285 }
286 if (timeout < 0 && timeout != -1) {
287 PyErr_SetString(PyExc_ValueError, "timeout value must be "
288 "strictly positive");
289 return NULL;
290 }
291 if (!blocking)
292 microseconds = 0;
293 else if (timeout == -1)
294 microseconds = -1;
295 else {
296 timeout *= 1e6;
297 if (timeout >= (double) PY_TIMEOUT_MAX) {
298 PyErr_SetString(PyExc_OverflowError,
299 "timeout value is too large");
300 return NULL;
301 }
302 microseconds = (PY_TIMEOUT_T) timeout;
303 }
Antoine Pitrou434736a2009-11-10 18:46:01 +0000304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305 tid = PyThread_get_thread_ident();
306 if (self->rlock_count > 0 && tid == self->rlock_owner) {
307 unsigned long count = self->rlock_count + 1;
308 if (count <= self->rlock_count) {
309 PyErr_SetString(PyExc_OverflowError,
310 "Internal lock count overflowed");
311 return NULL;
312 }
313 self->rlock_count = count;
314 Py_RETURN_TRUE;
315 }
Antoine Pitrou434736a2009-11-10 18:46:01 +0000316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317 if (self->rlock_count > 0 ||
318 !PyThread_acquire_lock(self->rlock_lock, 0)) {
319 if (microseconds == 0) {
320 Py_RETURN_FALSE;
321 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000322 r = acquire_timed(self->rlock_lock, microseconds);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000323 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000324 if (r == PY_LOCK_ACQUIRED) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325 assert(self->rlock_count == 0);
326 self->rlock_owner = tid;
327 self->rlock_count = 1;
328 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000329 else if (r == PY_LOCK_INTR) {
330 return NULL;
331 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332
Antoine Pitrou810023d2010-12-15 22:59:16 +0000333 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000334}
335
336PyDoc_STRVAR(rlock_acquire_doc,
337"acquire(blocking=True) -> bool\n\
338\n\
339Lock the lock. `blocking` indicates whether we should wait\n\
340for the lock to be available or not. If `blocking` is False\n\
341and another thread holds the lock, the method will return False\n\
342immediately. If `blocking` is True and another thread holds\n\
343the lock, the method will wait for the lock to be released,\n\
344take it and then return True.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000345(note: the blocking operation is interruptible.)\n\
Antoine Pitrou434736a2009-11-10 18:46:01 +0000346\n\
347In all other cases, the method will return True immediately.\n\
348Precisely, if the current thread already holds the lock, its\n\
349internal counter is simply incremented. If nobody holds the lock,\n\
350the lock is taken and its internal counter initialized to 1.");
351
352static PyObject *
353rlock_release(rlockobject *self)
354{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000355 long tid = PyThread_get_thread_ident();
Antoine Pitrou434736a2009-11-10 18:46:01 +0000356
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 if (self->rlock_count == 0 || self->rlock_owner != tid) {
358 PyErr_SetString(PyExc_RuntimeError,
359 "cannot release un-acquired lock");
360 return NULL;
361 }
362 if (--self->rlock_count == 0) {
363 self->rlock_owner = 0;
364 PyThread_release_lock(self->rlock_lock);
365 }
366 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000367}
368
369PyDoc_STRVAR(rlock_release_doc,
370"release()\n\
371\n\
372Release the lock, allowing another thread that is blocked waiting for\n\
373the lock to acquire the lock. The lock must be in the locked state,\n\
374and must be locked by the same thread that unlocks it; otherwise a\n\
375`RuntimeError` is raised.\n\
376\n\
377Do note that if the lock was acquire()d several times in a row by the\n\
378current thread, release() needs to be called as many times for the lock\n\
379to be available for other threads.");
380
381static PyObject *
382rlock_acquire_restore(rlockobject *self, PyObject *arg)
383{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384 long owner;
385 unsigned long count;
386 int r = 1;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 if (!PyArg_ParseTuple(arg, "kl:_acquire_restore", &count, &owner))
389 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 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;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000404}
405
406PyDoc_STRVAR(rlock_acquire_restore_doc,
407"_acquire_restore(state) -> None\n\
408\n\
409For internal use by `threading.Condition`.");
410
411static PyObject *
412rlock_release_save(rlockobject *self)
413{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000414 long owner;
415 unsigned long count;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000417 owner = self->rlock_owner;
418 count = self->rlock_count;
419 self->rlock_count = 0;
420 self->rlock_owner = 0;
421 PyThread_release_lock(self->rlock_lock);
422 return Py_BuildValue("kl", count, owner);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000423}
424
425PyDoc_STRVAR(rlock_release_save_doc,
426"_release_save() -> tuple\n\
427\n\
428For internal use by `threading.Condition`.");
429
430
431static PyObject *
432rlock_is_owned(rlockobject *self)
433{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434 long tid = PyThread_get_thread_ident();
435
436 if (self->rlock_count > 0 && self->rlock_owner == tid) {
437 Py_RETURN_TRUE;
438 }
439 Py_RETURN_FALSE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000440}
441
442PyDoc_STRVAR(rlock_is_owned_doc,
443"_is_owned() -> bool\n\
444\n\
445For internal use by `threading.Condition`.");
446
447static PyObject *
448rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
449{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000450 rlockobject *self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000452 self = (rlockobject *) type->tp_alloc(type, 0);
453 if (self != NULL) {
454 self->rlock_lock = PyThread_allocate_lock();
455 if (self->rlock_lock == NULL) {
456 type->tp_free(self);
457 PyErr_SetString(ThreadError, "can't allocate lock");
458 return NULL;
459 }
460 self->in_weakreflist = NULL;
461 self->rlock_owner = 0;
462 self->rlock_count = 0;
463 }
Antoine Pitrou434736a2009-11-10 18:46:01 +0000464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000465 return (PyObject *) self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000466}
467
468static PyObject *
469rlock_repr(rlockobject *self)
470{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000471 return PyUnicode_FromFormat("<%s owner=%ld count=%lu>",
472 Py_TYPE(self)->tp_name, self->rlock_owner, self->rlock_count);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000473}
474
475
476static PyMethodDef rlock_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000477 {"acquire", (PyCFunction)rlock_acquire,
478 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
479 {"release", (PyCFunction)rlock_release,
480 METH_NOARGS, rlock_release_doc},
481 {"_is_owned", (PyCFunction)rlock_is_owned,
482 METH_NOARGS, rlock_is_owned_doc},
483 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
484 METH_O, rlock_acquire_restore_doc},
485 {"_release_save", (PyCFunction)rlock_release_save,
486 METH_NOARGS, rlock_release_save_doc},
487 {"__enter__", (PyCFunction)rlock_acquire,
488 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
489 {"__exit__", (PyCFunction)rlock_release,
490 METH_VARARGS, rlock_release_doc},
491 {NULL, NULL} /* sentinel */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000492};
493
494
495static PyTypeObject RLocktype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 PyVarObject_HEAD_INIT(&PyType_Type, 0)
497 "_thread.RLock", /*tp_name*/
498 sizeof(rlockobject), /*tp_size*/
499 0, /*tp_itemsize*/
500 /* methods */
501 (destructor)rlock_dealloc, /*tp_dealloc*/
502 0, /*tp_print*/
503 0, /*tp_getattr*/
504 0, /*tp_setattr*/
505 0, /*tp_reserved*/
506 (reprfunc)rlock_repr, /*tp_repr*/
507 0, /*tp_as_number*/
508 0, /*tp_as_sequence*/
509 0, /*tp_as_mapping*/
510 0, /*tp_hash*/
511 0, /*tp_call*/
512 0, /*tp_str*/
513 0, /*tp_getattro*/
514 0, /*tp_setattro*/
515 0, /*tp_as_buffer*/
516 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
517 0, /*tp_doc*/
518 0, /*tp_traverse*/
519 0, /*tp_clear*/
520 0, /*tp_richcompare*/
521 offsetof(rlockobject, in_weakreflist), /*tp_weaklistoffset*/
522 0, /*tp_iter*/
523 0, /*tp_iternext*/
524 rlock_methods, /*tp_methods*/
525 0, /* tp_members */
526 0, /* tp_getset */
527 0, /* tp_base */
528 0, /* tp_dict */
529 0, /* tp_descr_get */
530 0, /* tp_descr_set */
531 0, /* tp_dictoffset */
532 0, /* tp_init */
533 PyType_GenericAlloc, /* tp_alloc */
534 rlock_new /* tp_new */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000535};
536
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000537static lockobject *
538newlockobject(void)
539{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 lockobject *self;
541 self = PyObject_New(lockobject, &Locktype);
542 if (self == NULL)
543 return NULL;
544 self->lock_lock = PyThread_allocate_lock();
545 self->in_weakreflist = NULL;
546 if (self->lock_lock == NULL) {
547 Py_DECREF(self);
548 PyErr_SetString(ThreadError, "can't allocate lock");
549 return NULL;
550 }
551 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000552}
553
Jim Fultond15dc062004-07-14 19:11:50 +0000554/* Thread-local objects */
555
556#include "structmember.h"
557
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000558/* Quick overview:
559
560 We need to be able to reclaim reference cycles as soon as possible
561 (both when a thread is being terminated, or a thread-local object
562 becomes unreachable from user data). Constraints:
563 - it must not be possible for thread-state dicts to be involved in
564 reference cycles (otherwise the cyclic GC will refuse to consider
565 objects referenced from a reachable thread-state dict, even though
566 local_dealloc would clear them)
567 - the death of a thread-state dict must still imply destruction of the
568 corresponding local dicts in all thread-local objects.
569
570 Our implementation uses small "localdummy" objects in order to break
571 the reference chain. These trivial objects are hashable (using the
572 default scheme of identity hashing) and weakrefable.
573 Each thread-state holds a separate localdummy for each local object
574 (as a /strong reference/),
575 and each thread-local object holds a dict mapping /weak references/
576 of localdummies to local dicts.
577
578 Therefore:
579 - only the thread-state dict holds a strong reference to the dummies
580 - only the thread-local object holds a strong reference to the local dicts
581 - only outside objects (application- or library-level) hold strong
582 references to the thread-local objects
583 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
584 dummies attached to that thread are called, and destroy the corresponding
585 local dicts from thread-local objects
586 - as soon as a thread-local object is destroyed, its local dicts are
587 destroyed and its dummies are manually removed from all thread states
588 - the GC can do its work correctly when a thread-local object is dangling,
589 without any interference from the thread-state dicts
590
591 As an additional optimization, each localdummy holds a borrowed reference
592 to the corresponding localdict. This borrowed reference is only used
593 by the thread-local object which has created the localdummy, which should
594 guarantee that the localdict still exists when accessed.
595*/
596
597typedef struct {
598 PyObject_HEAD
599 PyObject *localdict; /* Borrowed reference! */
600 PyObject *weakreflist; /* List of weak references to self */
601} localdummyobject;
602
603static void
604localdummy_dealloc(localdummyobject *self)
605{
606 if (self->weakreflist != NULL)
607 PyObject_ClearWeakRefs((PyObject *) self);
608 Py_TYPE(self)->tp_free((PyObject*)self);
609}
610
611static PyTypeObject localdummytype = {
612 PyVarObject_HEAD_INIT(NULL, 0)
613 /* tp_name */ "_thread._localdummy",
614 /* tp_basicsize */ sizeof(localdummyobject),
615 /* tp_itemsize */ 0,
616 /* tp_dealloc */ (destructor)localdummy_dealloc,
617 /* tp_print */ 0,
618 /* tp_getattr */ 0,
619 /* tp_setattr */ 0,
620 /* tp_reserved */ 0,
621 /* tp_repr */ 0,
622 /* tp_as_number */ 0,
623 /* tp_as_sequence */ 0,
624 /* tp_as_mapping */ 0,
625 /* tp_hash */ 0,
626 /* tp_call */ 0,
627 /* tp_str */ 0,
628 /* tp_getattro */ 0,
629 /* tp_setattro */ 0,
630 /* tp_as_buffer */ 0,
631 /* tp_flags */ Py_TPFLAGS_DEFAULT,
632 /* tp_doc */ "Thread-local dummy",
633 /* tp_traverse */ 0,
634 /* tp_clear */ 0,
635 /* tp_richcompare */ 0,
636 /* tp_weaklistoffset */ offsetof(localdummyobject, weakreflist)
637};
638
639
Jim Fultond15dc062004-07-14 19:11:50 +0000640typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 PyObject_HEAD
642 PyObject *key;
643 PyObject *args;
644 PyObject *kw;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000645 PyObject *weakreflist; /* List of weak references to self */
646 /* A {localdummy weakref -> localdict} dict */
647 PyObject *dummies;
648 /* The callback for weakrefs to localdummies */
649 PyObject *wr_callback;
Jim Fultond15dc062004-07-14 19:11:50 +0000650} localobject;
651
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000652/* Forward declaration */
653static PyObject *_ldict(localobject *self);
654static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
655
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000656/* Create and register the dummy for the current thread.
657 Returns a borrowed reference of the corresponding local dict */
658static PyObject *
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000659_local_create_dummy(localobject *self)
660{
661 PyObject *tdict, *ldict = NULL, *wr = NULL;
662 localdummyobject *dummy = NULL;
663 int r;
664
665 tdict = PyThreadState_GetDict();
666 if (tdict == NULL) {
667 PyErr_SetString(PyExc_SystemError,
668 "Couldn't get thread-state dictionary");
669 goto err;
670 }
671
672 ldict = PyDict_New();
673 if (ldict == NULL)
674 goto err;
675 dummy = (localdummyobject *) localdummytype.tp_alloc(&localdummytype, 0);
676 if (dummy == NULL)
677 goto err;
678 dummy->localdict = ldict;
679 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
680 if (wr == NULL)
681 goto err;
682
683 /* As a side-effect, this will cache the weakref's hash before the
684 dummy gets deleted */
685 r = PyDict_SetItem(self->dummies, wr, ldict);
686 if (r < 0)
687 goto err;
688 Py_CLEAR(wr);
689 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
690 if (r < 0)
691 goto err;
692 Py_CLEAR(dummy);
693
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000694 Py_DECREF(ldict);
695 return ldict;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000696
697err:
698 Py_XDECREF(ldict);
699 Py_XDECREF(wr);
700 Py_XDECREF(dummy);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000701 return NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000702}
703
Jim Fultond15dc062004-07-14 19:11:50 +0000704static PyObject *
705local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
706{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707 localobject *self;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000708 PyObject *wr;
709 static PyMethodDef wr_callback_def = {
710 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
711 };
Jim Fultond15dc062004-07-14 19:11:50 +0000712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000713 if (type->tp_init == PyBaseObject_Type.tp_init
714 && ((args && PyObject_IsTrue(args))
715 || (kw && PyObject_IsTrue(kw)))) {
716 PyErr_SetString(PyExc_TypeError,
717 "Initialization arguments are not supported");
718 return NULL;
719 }
Jim Fultond15dc062004-07-14 19:11:50 +0000720
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000721 self = (localobject *)type->tp_alloc(type, 0);
722 if (self == NULL)
723 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 Py_XINCREF(args);
726 self->args = args;
727 Py_XINCREF(kw);
728 self->kw = kw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000729 self->key = PyUnicode_FromFormat("thread.local.%p", self);
730 if (self->key == NULL)
731 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000732
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000733 self->dummies = PyDict_New();
734 if (self->dummies == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000736
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000737 /* We use a weak reference to self in the callback closure
738 in order to avoid spurious reference cycles */
739 wr = PyWeakref_NewRef((PyObject *) self, NULL);
740 if (wr == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 goto err;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000742 self->wr_callback = PyCFunction_New(&wr_callback_def, wr);
743 Py_DECREF(wr);
744 if (self->wr_callback == NULL)
745 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000746
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000747 if (_local_create_dummy(self) == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000750 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000751
752 err:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753 Py_DECREF(self);
754 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000755}
756
757static int
758local_traverse(localobject *self, visitproc visit, void *arg)
759{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760 Py_VISIT(self->args);
761 Py_VISIT(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000762 Py_VISIT(self->dummies);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000764}
765
766static int
767local_clear(localobject *self)
768{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000769 PyThreadState *tstate;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 Py_CLEAR(self->args);
771 Py_CLEAR(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000772 Py_CLEAR(self->dummies);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000773 Py_CLEAR(self->wr_callback);
774 /* Remove all strong references to dummies from the thread states */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 if (self->key
776 && (tstate = PyThreadState_Get())
777 && tstate->interp) {
778 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
779 tstate;
780 tstate = PyThreadState_Next(tstate))
781 if (tstate->dict &&
782 PyDict_GetItem(tstate->dict, self->key))
783 PyDict_DelItem(tstate->dict, self->key);
784 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000785 return 0;
786}
Jim Fultond15dc062004-07-14 19:11:50 +0000787
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000788static void
789local_dealloc(localobject *self)
790{
791 /* Weakrefs must be invalidated right now, otherwise they can be used
792 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
793 if (self->weakreflist != NULL)
794 PyObject_ClearWeakRefs((PyObject *) self);
795
796 PyObject_GC_UnTrack(self);
797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 local_clear(self);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000799 Py_XDECREF(self->key);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000800 Py_TYPE(self)->tp_free((PyObject*)self);
Jim Fultond15dc062004-07-14 19:11:50 +0000801}
802
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000803/* Returns a borrowed reference to the local dict, creating it if necessary */
Jim Fultond15dc062004-07-14 19:11:50 +0000804static PyObject *
805_ldict(localobject *self)
806{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000807 PyObject *tdict, *ldict, *dummy;
Jim Fultond15dc062004-07-14 19:11:50 +0000808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 tdict = PyThreadState_GetDict();
810 if (tdict == NULL) {
811 PyErr_SetString(PyExc_SystemError,
812 "Couldn't get thread-state dictionary");
813 return NULL;
814 }
Jim Fultond15dc062004-07-14 19:11:50 +0000815
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000816 dummy = PyDict_GetItem(tdict, self->key);
817 if (dummy == NULL) {
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000818 ldict = _local_create_dummy(self);
819 if (ldict == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000820 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000822 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
823 Py_TYPE(self)->tp_init((PyObject*)self,
824 self->args, self->kw) < 0) {
825 /* we need to get rid of ldict from thread so
826 we create a new one the next time we do an attr
827 acces */
828 PyDict_DelItem(tdict, self->key);
829 return NULL;
830 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000831 }
832 else {
833 assert(Py_TYPE(dummy) == &localdummytype);
834 ldict = ((localdummyobject *) dummy)->localdict;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 }
Jim Fultond15dc062004-07-14 19:11:50 +0000836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000838}
839
Jim Fultond15dc062004-07-14 19:11:50 +0000840static int
841local_setattro(localobject *self, PyObject *name, PyObject *v)
842{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 PyObject *ldict;
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000844 int r;
Jim Fultond15dc062004-07-14 19:11:50 +0000845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 ldict = _ldict(self);
847 if (ldict == NULL)
848 return -1;
849
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000850 r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
851 if (r == 1) {
852 PyErr_Format(PyExc_AttributeError,
853 "'%.50s' object attribute '%U' is read-only",
854 Py_TYPE(self)->tp_name, name);
855 return -1;
856 }
857 if (r == -1)
858 return -1;
Jim Fultond15dc062004-07-14 19:11:50 +0000859
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000860 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
Jim Fultond15dc062004-07-14 19:11:50 +0000861}
862
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000863static PyObject *local_getattro(localobject *, PyObject *);
864
Jim Fultond15dc062004-07-14 19:11:50 +0000865static PyTypeObject localtype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000866 PyVarObject_HEAD_INIT(NULL, 0)
867 /* tp_name */ "_thread._local",
868 /* tp_basicsize */ sizeof(localobject),
869 /* tp_itemsize */ 0,
870 /* tp_dealloc */ (destructor)local_dealloc,
871 /* tp_print */ 0,
872 /* tp_getattr */ 0,
873 /* tp_setattr */ 0,
874 /* tp_reserved */ 0,
875 /* tp_repr */ 0,
876 /* tp_as_number */ 0,
877 /* tp_as_sequence */ 0,
878 /* tp_as_mapping */ 0,
879 /* tp_hash */ 0,
880 /* tp_call */ 0,
881 /* tp_str */ 0,
882 /* tp_getattro */ (getattrofunc)local_getattro,
883 /* tp_setattro */ (setattrofunc)local_setattro,
884 /* tp_as_buffer */ 0,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000885 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
886 | Py_TPFLAGS_HAVE_GC,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 /* tp_doc */ "Thread-local data",
888 /* tp_traverse */ (traverseproc)local_traverse,
889 /* tp_clear */ (inquiry)local_clear,
890 /* tp_richcompare */ 0,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000891 /* tp_weaklistoffset */ offsetof(localobject, weakreflist),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000892 /* tp_iter */ 0,
893 /* tp_iternext */ 0,
894 /* tp_methods */ 0,
895 /* tp_members */ 0,
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000896 /* tp_getset */ 0,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000897 /* tp_base */ 0,
898 /* tp_dict */ 0, /* internal use */
899 /* tp_descr_get */ 0,
900 /* tp_descr_set */ 0,
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000901 /* tp_dictoffset */ 0,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000902 /* tp_init */ 0,
903 /* tp_alloc */ 0,
904 /* tp_new */ local_new,
905 /* tp_free */ 0, /* Low-level free-mem routine */
906 /* tp_is_gc */ 0, /* For PyObject_IS_GC */
Jim Fultond15dc062004-07-14 19:11:50 +0000907};
908
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000909static PyObject *
910local_getattro(localobject *self, PyObject *name)
911{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000912 PyObject *ldict, *value;
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000913 int r;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000914
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000915 ldict = _ldict(self);
916 if (ldict == NULL)
917 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000918
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000919 r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
920 if (r == 1) {
921 Py_INCREF(ldict);
922 return ldict;
923 }
924 if (r == -1)
925 return NULL;
926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927 if (Py_TYPE(self) != &localtype)
928 /* use generic lookup for subtypes */
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000929 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000930
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000931 /* Optimization: just look in dict ourselves */
932 value = PyDict_GetItem(ldict, name);
933 if (value == NULL)
934 /* Fall back on generic to get __class__ and __dict__ */
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000935 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000936
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000937 Py_INCREF(value);
938 return value;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000939}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000940
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000941/* Called when a dummy is destroyed. */
942static PyObject *
943_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
944{
945 PyObject *obj;
946 localobject *self;
947 assert(PyWeakref_CheckRef(localweakref));
948 obj = PyWeakref_GET_OBJECT(localweakref);
949 if (obj == Py_None)
950 Py_RETURN_NONE;
951 Py_INCREF(obj);
952 assert(PyObject_TypeCheck(obj, &localtype));
953 /* If the thread-local object is still alive and not being cleared,
954 remove the corresponding local dict */
955 self = (localobject *) obj;
956 if (self->dummies != NULL) {
957 PyObject *ldict;
958 ldict = PyDict_GetItem(self->dummies, dummyweakref);
959 if (ldict != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000960 PyDict_DelItem(self->dummies, dummyweakref);
961 }
962 if (PyErr_Occurred())
963 PyErr_WriteUnraisable(obj);
964 }
965 Py_DECREF(obj);
966 Py_RETURN_NONE;
967}
968
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000969/* Module functions */
970
Guido van Rossuma027efa1997-05-05 20:56:21 +0000971struct bootstate {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000972 PyInterpreterState *interp;
973 PyObject *func;
974 PyObject *args;
975 PyObject *keyw;
976 PyThreadState *tstate;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000977};
978
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000979static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000980t_bootstrap(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000981{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000982 struct bootstate *boot = (struct bootstate *) boot_raw;
983 PyThreadState *tstate;
984 PyObject *res;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000985
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000986 tstate = boot->tstate;
987 tstate->thread_id = PyThread_get_thread_ident();
988 _PyThreadState_Init(tstate);
989 PyEval_AcquireThread(tstate);
990 nb_threads++;
991 res = PyEval_CallObjectWithKeywords(
992 boot->func, boot->args, boot->keyw);
993 if (res == NULL) {
994 if (PyErr_ExceptionMatches(PyExc_SystemExit))
995 PyErr_Clear();
996 else {
997 PyObject *file;
998 PySys_WriteStderr(
999 "Unhandled exception in thread started by ");
1000 file = PySys_GetObject("stderr");
1001 if (file != NULL && file != Py_None)
1002 PyFile_WriteObject(boot->func, file, 0);
1003 else
1004 PyObject_Print(boot->func, stderr, 0);
1005 PySys_WriteStderr("\n");
1006 PyErr_PrintEx(0);
1007 }
1008 }
1009 else
1010 Py_DECREF(res);
1011 Py_DECREF(boot->func);
1012 Py_DECREF(boot->args);
1013 Py_XDECREF(boot->keyw);
1014 PyMem_DEL(boot_raw);
1015 nb_threads--;
1016 PyThreadState_Clear(tstate);
1017 PyThreadState_DeleteCurrent();
1018 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001019}
1020
Barry Warsawd0c10421996-12-17 00:05:22 +00001021static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +00001022thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001023{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 PyObject *func, *args, *keyw = NULL;
1025 struct bootstate *boot;
1026 long ident;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001028 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1029 &func, &args, &keyw))
1030 return NULL;
1031 if (!PyCallable_Check(func)) {
1032 PyErr_SetString(PyExc_TypeError,
1033 "first arg must be callable");
1034 return NULL;
1035 }
1036 if (!PyTuple_Check(args)) {
1037 PyErr_SetString(PyExc_TypeError,
1038 "2nd arg must be a tuple");
1039 return NULL;
1040 }
1041 if (keyw != NULL && !PyDict_Check(keyw)) {
1042 PyErr_SetString(PyExc_TypeError,
1043 "optional 3rd arg must be a dictionary");
1044 return NULL;
1045 }
1046 boot = PyMem_NEW(struct bootstate, 1);
1047 if (boot == NULL)
1048 return PyErr_NoMemory();
1049 boot->interp = PyThreadState_GET()->interp;
1050 boot->func = func;
1051 boot->args = args;
1052 boot->keyw = keyw;
1053 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1054 if (boot->tstate == NULL) {
1055 PyMem_DEL(boot);
1056 return PyErr_NoMemory();
1057 }
1058 Py_INCREF(func);
1059 Py_INCREF(args);
1060 Py_XINCREF(keyw);
1061 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
1062 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
1063 if (ident == -1) {
1064 PyErr_SetString(ThreadError, "can't start new thread");
1065 Py_DECREF(func);
1066 Py_DECREF(args);
1067 Py_XDECREF(keyw);
1068 PyThreadState_Clear(boot->tstate);
1069 PyMem_DEL(boot);
1070 return NULL;
1071 }
1072 return PyLong_FromLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001073}
1074
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001075PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +00001076"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001077(start_new() is an obsolete synonym)\n\
1078\n\
Guido van Rossum3c288632001-10-16 21:13:49 +00001079Start a new thread and return its identifier. The thread will call the\n\
1080function with positional arguments from the tuple args and keyword arguments\n\
1081taken from the optional dictionary kwargs. The thread exits when the\n\
1082function returns; the return value is ignored. The thread will also exit\n\
1083when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001084printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001085
Barry Warsawd0c10421996-12-17 00:05:22 +00001086static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +00001087thread_PyThread_exit_thread(PyObject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001088{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001089 PyErr_SetNone(PyExc_SystemExit);
1090 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001091}
1092
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001093PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001094"exit()\n\
Guido van Rossum65d5b571998-12-21 19:32:43 +00001095(PyThread_exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001096\n\
1097This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001098thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001099
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001100static PyObject *
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +00001101thread_PyThread_interrupt_main(PyObject * self)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001102{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001103 PyErr_SetInterrupt();
1104 Py_INCREF(Py_None);
1105 return Py_None;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001106}
1107
1108PyDoc_STRVAR(interrupt_doc,
1109"interrupt_main()\n\
1110\n\
1111Raise a KeyboardInterrupt in the main thread.\n\
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +00001112A subthread can use this function to interrupt the main thread."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001113);
1114
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001115static lockobject *newlockobject(void);
1116
Barry Warsawd0c10421996-12-17 00:05:22 +00001117static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +00001118thread_PyThread_allocate_lock(PyObject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001119{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001120 return (PyObject *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001121}
1122
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001123PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001124"allocate_lock() -> lock object\n\
1125(allocate() is an obsolete synonym)\n\
1126\n\
Alexander Belopolsky977a6842010-08-16 20:17:07 +00001127Create a new lock object. See help(LockType) for information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001128
Barry Warsawd0c10421996-12-17 00:05:22 +00001129static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +00001130thread_get_ident(PyObject *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +00001131{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 long ident;
1133 ident = PyThread_get_thread_ident();
1134 if (ident == -1) {
1135 PyErr_SetString(ThreadError, "no current thread ident");
1136 return NULL;
1137 }
1138 return PyLong_FromLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001139}
1140
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001141PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001142"get_ident() -> integer\n\
1143\n\
1144Return a non-zero integer that uniquely identifies the current thread\n\
1145amongst other threads that exist simultaneously.\n\
1146This may be used to identify per-thread resources.\n\
1147Even though on some platforms threads identities may appear to be\n\
1148allocated consecutive numbers starting at 1, this behavior should not\n\
1149be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001150A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001151
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001152static PyObject *
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001153thread__count(PyObject *self)
1154{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001155 return PyLong_FromLong(nb_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001156}
1157
1158PyDoc_STRVAR(_count_doc,
1159"_count() -> integer\n\
1160\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001161\
1162Return the number of currently running Python threads, excluding \n\
1163the main thread. The returned number comprises all threads created\n\
1164through `start_new_thread()` as well as `threading.Thread`, and not\n\
1165yet finished.\n\
1166\n\
1167This function is meant for internal and specialized purposes only.\n\
1168In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001169
1170static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001171thread_stack_size(PyObject *self, PyObject *args)
1172{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001173 size_t old_size;
1174 Py_ssize_t new_size = 0;
1175 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001176
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001177 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1178 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001180 if (new_size < 0) {
1181 PyErr_SetString(PyExc_ValueError,
1182 "size must be 0 or a positive value");
1183 return NULL;
1184 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001185
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001186 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001187
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001188 rc = PyThread_set_stacksize((size_t) new_size);
1189 if (rc == -1) {
1190 PyErr_Format(PyExc_ValueError,
1191 "size not valid: %zd bytes",
1192 new_size);
1193 return NULL;
1194 }
1195 if (rc == -2) {
1196 PyErr_SetString(ThreadError,
1197 "setting stack size not supported");
1198 return NULL;
1199 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001201 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001202}
1203
1204PyDoc_STRVAR(stack_size_doc,
1205"stack_size([size]) -> size\n\
1206\n\
1207Return the thread stack size used when creating new threads. The\n\
1208optional size argument specifies the stack size (in bytes) to be used\n\
1209for subsequently created threads, and must be 0 (use platform or\n\
1210configured default) or a positive integer value of at least 32,768 (32k).\n\
1211If changing the thread stack size is unsupported, a ThreadError\n\
1212exception is raised. If the specified size is invalid, a ValueError\n\
1213exception is raised, and the stack size is unmodified. 32k bytes\n\
1214 currently the minimum supported stack size value to guarantee\n\
1215sufficient stack space for the interpreter itself.\n\
1216\n\
1217Note that some platforms may have particular restrictions on values for\n\
1218the stack size, such as requiring a minimum stack size larger than 32kB or\n\
1219requiring allocation in multiples of the system memory page size\n\
1220- platform documentation should be referred to for more information\n\
1221(4kB pages are common; using multiples of 4096 for the stack size is\n\
1222the suggested approach in the absence of more specific information).");
1223
Barry Warsawd0c10421996-12-17 00:05:22 +00001224static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
1226 METH_VARARGS,
1227 start_new_doc},
1228 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
1229 METH_VARARGS,
1230 start_new_doc},
1231 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
1232 METH_NOARGS, allocate_doc},
1233 {"allocate", (PyCFunction)thread_PyThread_allocate_lock,
1234 METH_NOARGS, allocate_doc},
1235 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread,
1236 METH_NOARGS, exit_doc},
1237 {"exit", (PyCFunction)thread_PyThread_exit_thread,
1238 METH_NOARGS, exit_doc},
1239 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1240 METH_NOARGS, interrupt_doc},
1241 {"get_ident", (PyCFunction)thread_get_ident,
1242 METH_NOARGS, get_ident_doc},
1243 {"_count", (PyCFunction)thread__count,
1244 METH_NOARGS, _count_doc},
1245 {"stack_size", (PyCFunction)thread_stack_size,
1246 METH_VARARGS,
1247 stack_size_doc},
1248 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001249};
1250
1251
1252/* Initialization function */
1253
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001254PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001255"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001256The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001257
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001258PyDoc_STRVAR(lock_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001259"A lock object is a synchronization primitive. To create a lock,\n\
Guido van Rossum65d5b571998-12-21 19:32:43 +00001260call the PyThread_allocate_lock() function. Methods are:\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001261\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001262acquire() -- lock the lock, possibly blocking until it can be obtained\n\
1263release() -- unlock of the lock\n\
1264locked() -- test whether the lock is currently locked\n\
1265\n\
1266A lock is not owned by the thread that locked it; another thread may\n\
1267unlock it. A thread attempting to lock a lock that it has already locked\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001268will block until another thread unlocks it. Deadlocks may ensue.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001269
Martin v. Löwis1a214512008-06-11 05:26:20 +00001270static struct PyModuleDef threadmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 PyModuleDef_HEAD_INIT,
1272 "_thread",
1273 thread_doc,
1274 -1,
1275 thread_methods,
1276 NULL,
1277 NULL,
1278 NULL,
1279 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001280};
1281
1282
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001283PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001284PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001285{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 PyObject *m, *d, *timeout_max;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 /* Initialize types: */
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001289 if (PyType_Ready(&localdummytype) < 0)
1290 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 if (PyType_Ready(&localtype) < 0)
1292 return NULL;
1293 if (PyType_Ready(&Locktype) < 0)
1294 return NULL;
1295 if (PyType_Ready(&RLocktype) < 0)
1296 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 /* Create the module and add the functions */
1299 m = PyModule_Create(&threadmodule);
1300 if (m == NULL)
1301 return NULL;
Antoine Pitrou7c3e5772010-04-14 15:44:10 +00001302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 timeout_max = PyFloat_FromDouble(PY_TIMEOUT_MAX / 1000000);
1304 if (!timeout_max)
1305 return NULL;
1306 if (PyModule_AddObject(m, "TIMEOUT_MAX", timeout_max) < 0)
1307 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 /* Add a symbolic constant */
1310 d = PyModule_GetDict(m);
Antoine Pitroufcf81fd2011-02-28 22:03:34 +00001311 ThreadError = PyExc_RuntimeError;
1312 Py_INCREF(ThreadError);
1313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 PyDict_SetItemString(d, "error", ThreadError);
1315 Locktype.tp_doc = lock_doc;
1316 Py_INCREF(&Locktype);
1317 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
Antoine Pitrou434736a2009-11-10 18:46:01 +00001318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 Py_INCREF(&RLocktype);
1320 if (PyModule_AddObject(m, "RLock", (PyObject *)&RLocktype) < 0)
1321 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +00001322
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 Py_INCREF(&localtype);
1324 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
1325 return NULL;
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001327 nb_threads = 0;
1328
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +00001329 str_dict = PyUnicode_InternFromString("__dict__");
1330 if (str_dict == NULL)
1331 return NULL;
1332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 /* Initialize the C thread library */
1334 PyThread_init_thread();
1335 return m;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001336}