blob: a94b1995727103041e7e9d1de822f415b60cf53e [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;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000018
19/* Lock objects */
20
21typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 PyObject_HEAD
23 PyThread_type_lock lock_lock;
24 PyObject *in_weakreflist;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000025} lockobject;
26
Guido van Rossum1984f1e1992-08-04 12:41:02 +000027static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +000028lock_dealloc(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000029{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000030 if (self->in_weakreflist != NULL)
31 PyObject_ClearWeakRefs((PyObject *) self);
32 if (self->lock_lock != NULL) {
33 /* Unlock the lock so it's safe to free it */
34 PyThread_acquire_lock(self->lock_lock, 0);
35 PyThread_release_lock(self->lock_lock);
36
37 PyThread_free_lock(self->lock_lock);
38 }
39 PyObject_Del(self);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000040}
41
Barry Warsawd0c10421996-12-17 00:05:22 +000042static PyObject *
Antoine Pitrou7c3e5772010-04-14 15:44:10 +000043lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000044{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 char *kwlist[] = {"blocking", "timeout", NULL};
46 int blocking = 1;
47 double timeout = -1;
48 PY_TIMEOUT_T microseconds;
49 int r;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000051 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|id:acquire", kwlist,
52 &blocking, &timeout))
53 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000055 if (!blocking && timeout != -1) {
56 PyErr_SetString(PyExc_ValueError, "can't specify a timeout "
57 "for a non-blocking call");
58 return NULL;
59 }
60 if (timeout < 0 && timeout != -1) {
61 PyErr_SetString(PyExc_ValueError, "timeout value must be "
62 "strictly positive");
63 return NULL;
64 }
65 if (!blocking)
66 microseconds = 0;
67 else if (timeout == -1)
68 microseconds = -1;
69 else {
70 timeout *= 1e6;
71 if (timeout >= (double) PY_TIMEOUT_MAX) {
72 PyErr_SetString(PyExc_OverflowError,
73 "timeout value is too large");
74 return NULL;
75 }
76 microseconds = (PY_TIMEOUT_T) timeout;
77 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +000078
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 Py_BEGIN_ALLOW_THREADS
80 r = PyThread_acquire_lock_timed(self->lock_lock, microseconds);
81 Py_END_ALLOW_THREADS
82
83 return PyBool_FromLong(r);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000084}
85
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000086PyDoc_STRVAR(acquire_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +000087"acquire([wait]) -> None or bool\n\
Guido van Rossumf6694362006-03-10 02:28:35 +000088(acquire_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +000089\n\
90Lock the lock. Without argument, this blocks if the lock is already\n\
91locked (even by the same thread), waiting for another thread to release\n\
Guido van Rossum8fdc75b2002-04-07 06:32:21 +000092the lock, and return None once the lock is acquired.\n\
93With an argument, this will only block if the argument is true,\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +000094and the return value reflects whether the lock is acquired.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000095The blocking operation is not interruptible.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +000096
Barry Warsawd0c10421996-12-17 00:05:22 +000097static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +000098lock_PyThread_release_lock(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000099{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 /* Sanity check: the lock must be locked */
101 if (PyThread_acquire_lock(self->lock_lock, 0)) {
102 PyThread_release_lock(self->lock_lock);
103 PyErr_SetString(ThreadError, "release unlocked lock");
104 return NULL;
105 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 PyThread_release_lock(self->lock_lock);
108 Py_INCREF(Py_None);
109 return Py_None;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000110}
111
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000112PyDoc_STRVAR(release_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000113"release()\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000114(release_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000115\n\
116Release the lock, allowing another thread that is blocked waiting for\n\
117the lock to acquire the lock. The lock must be in the locked state,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000118but it needn't be locked by the same thread that unlocks it.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000119
Barry Warsawd0c10421996-12-17 00:05:22 +0000120static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000121lock_locked_lock(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000122{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 if (PyThread_acquire_lock(self->lock_lock, 0)) {
124 PyThread_release_lock(self->lock_lock);
125 return PyBool_FromLong(0L);
126 }
127 return PyBool_FromLong(1L);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000128}
129
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000130PyDoc_STRVAR(locked_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000131"locked() -> bool\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000132(locked_lock() is an obsolete synonym)\n\
133\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000134Return whether the lock is in the locked state.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000135
Barry Warsawd0c10421996-12-17 00:05:22 +0000136static PyMethodDef lock_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000137 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
138 METH_VARARGS | METH_KEYWORDS, acquire_doc},
139 {"acquire", (PyCFunction)lock_PyThread_acquire_lock,
140 METH_VARARGS | METH_KEYWORDS, acquire_doc},
141 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
142 METH_NOARGS, release_doc},
143 {"release", (PyCFunction)lock_PyThread_release_lock,
144 METH_NOARGS, release_doc},
145 {"locked_lock", (PyCFunction)lock_locked_lock,
146 METH_NOARGS, locked_doc},
147 {"locked", (PyCFunction)lock_locked_lock,
148 METH_NOARGS, locked_doc},
149 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock,
150 METH_VARARGS | METH_KEYWORDS, acquire_doc},
151 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
152 METH_VARARGS, release_doc},
153 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000154};
155
Barry Warsawd0c10421996-12-17 00:05:22 +0000156static PyTypeObject Locktype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 PyVarObject_HEAD_INIT(&PyType_Type, 0)
158 "_thread.lock", /*tp_name*/
159 sizeof(lockobject), /*tp_size*/
160 0, /*tp_itemsize*/
161 /* methods */
162 (destructor)lock_dealloc, /*tp_dealloc*/
163 0, /*tp_print*/
164 0, /*tp_getattr*/
165 0, /*tp_setattr*/
166 0, /*tp_reserved*/
167 0, /*tp_repr*/
168 0, /*tp_as_number*/
169 0, /*tp_as_sequence*/
170 0, /*tp_as_mapping*/
171 0, /*tp_hash*/
172 0, /*tp_call*/
173 0, /*tp_str*/
174 0, /*tp_getattro*/
175 0, /*tp_setattro*/
176 0, /*tp_as_buffer*/
177 Py_TPFLAGS_DEFAULT, /*tp_flags*/
178 0, /*tp_doc*/
179 0, /*tp_traverse*/
180 0, /*tp_clear*/
181 0, /*tp_richcompare*/
182 offsetof(lockobject, in_weakreflist), /*tp_weaklistoffset*/
183 0, /*tp_iter*/
184 0, /*tp_iternext*/
185 lock_methods, /*tp_methods*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000186};
187
Antoine Pitrou434736a2009-11-10 18:46:01 +0000188/* Recursive lock objects */
189
190typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 PyObject_HEAD
192 PyThread_type_lock rlock_lock;
193 long rlock_owner;
194 unsigned long rlock_count;
195 PyObject *in_weakreflist;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000196} rlockobject;
197
198static void
199rlock_dealloc(rlockobject *self)
200{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 assert(self->rlock_lock);
202 if (self->in_weakreflist != NULL)
203 PyObject_ClearWeakRefs((PyObject *) self);
204 /* Unlock the lock so it's safe to free it */
205 if (self->rlock_count > 0)
206 PyThread_release_lock(self->rlock_lock);
207
208 PyThread_free_lock(self->rlock_lock);
209 Py_TYPE(self)->tp_free(self);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000210}
211
212static PyObject *
213rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
214{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000215 char *kwlist[] = {"blocking", "timeout", NULL};
216 int blocking = 1;
217 double timeout = -1;
218 PY_TIMEOUT_T microseconds;
219 long tid;
220 int r = 1;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000221
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000222 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|id:acquire", kwlist,
223 &blocking, &timeout))
224 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 if (!blocking && timeout != -1) {
227 PyErr_SetString(PyExc_ValueError, "can't specify a timeout "
228 "for a non-blocking call");
229 return NULL;
230 }
231 if (timeout < 0 && timeout != -1) {
232 PyErr_SetString(PyExc_ValueError, "timeout value must be "
233 "strictly positive");
234 return NULL;
235 }
236 if (!blocking)
237 microseconds = 0;
238 else if (timeout == -1)
239 microseconds = -1;
240 else {
241 timeout *= 1e6;
242 if (timeout >= (double) PY_TIMEOUT_MAX) {
243 PyErr_SetString(PyExc_OverflowError,
244 "timeout value is too large");
245 return NULL;
246 }
247 microseconds = (PY_TIMEOUT_T) timeout;
248 }
Antoine Pitrou434736a2009-11-10 18:46:01 +0000249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000250 tid = PyThread_get_thread_ident();
251 if (self->rlock_count > 0 && tid == self->rlock_owner) {
252 unsigned long count = self->rlock_count + 1;
253 if (count <= self->rlock_count) {
254 PyErr_SetString(PyExc_OverflowError,
255 "Internal lock count overflowed");
256 return NULL;
257 }
258 self->rlock_count = count;
259 Py_RETURN_TRUE;
260 }
Antoine Pitrou434736a2009-11-10 18:46:01 +0000261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000262 if (self->rlock_count > 0 ||
263 !PyThread_acquire_lock(self->rlock_lock, 0)) {
264 if (microseconds == 0) {
265 Py_RETURN_FALSE;
266 }
267 Py_BEGIN_ALLOW_THREADS
268 r = PyThread_acquire_lock_timed(self->rlock_lock, microseconds);
269 Py_END_ALLOW_THREADS
270 }
271 if (r) {
272 assert(self->rlock_count == 0);
273 self->rlock_owner = tid;
274 self->rlock_count = 1;
275 }
276
277 return PyBool_FromLong(r);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000278}
279
280PyDoc_STRVAR(rlock_acquire_doc,
281"acquire(blocking=True) -> bool\n\
282\n\
283Lock the lock. `blocking` indicates whether we should wait\n\
284for the lock to be available or not. If `blocking` is False\n\
285and another thread holds the lock, the method will return False\n\
286immediately. If `blocking` is True and another thread holds\n\
287the lock, the method will wait for the lock to be released,\n\
288take it and then return True.\n\
289(note: the blocking operation is not interruptible.)\n\
290\n\
291In all other cases, the method will return True immediately.\n\
292Precisely, if the current thread already holds the lock, its\n\
293internal counter is simply incremented. If nobody holds the lock,\n\
294the lock is taken and its internal counter initialized to 1.");
295
296static PyObject *
297rlock_release(rlockobject *self)
298{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299 long tid = PyThread_get_thread_ident();
Antoine Pitrou434736a2009-11-10 18:46:01 +0000300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000301 if (self->rlock_count == 0 || self->rlock_owner != tid) {
302 PyErr_SetString(PyExc_RuntimeError,
303 "cannot release un-acquired lock");
304 return NULL;
305 }
306 if (--self->rlock_count == 0) {
307 self->rlock_owner = 0;
308 PyThread_release_lock(self->rlock_lock);
309 }
310 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000311}
312
313PyDoc_STRVAR(rlock_release_doc,
314"release()\n\
315\n\
316Release the lock, allowing another thread that is blocked waiting for\n\
317the lock to acquire the lock. The lock must be in the locked state,\n\
318and must be locked by the same thread that unlocks it; otherwise a\n\
319`RuntimeError` is raised.\n\
320\n\
321Do note that if the lock was acquire()d several times in a row by the\n\
322current thread, release() needs to be called as many times for the lock\n\
323to be available for other threads.");
324
325static PyObject *
326rlock_acquire_restore(rlockobject *self, PyObject *arg)
327{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000328 long owner;
329 unsigned long count;
330 int r = 1;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 if (!PyArg_ParseTuple(arg, "kl:_acquire_restore", &count, &owner))
333 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000335 if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
336 Py_BEGIN_ALLOW_THREADS
337 r = PyThread_acquire_lock(self->rlock_lock, 1);
338 Py_END_ALLOW_THREADS
339 }
340 if (!r) {
341 PyErr_SetString(ThreadError, "couldn't acquire lock");
342 return NULL;
343 }
344 assert(self->rlock_count == 0);
345 self->rlock_owner = owner;
346 self->rlock_count = count;
347 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000348}
349
350PyDoc_STRVAR(rlock_acquire_restore_doc,
351"_acquire_restore(state) -> None\n\
352\n\
353For internal use by `threading.Condition`.");
354
355static PyObject *
356rlock_release_save(rlockobject *self)
357{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000358 long owner;
359 unsigned long count;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000361 owner = self->rlock_owner;
362 count = self->rlock_count;
363 self->rlock_count = 0;
364 self->rlock_owner = 0;
365 PyThread_release_lock(self->rlock_lock);
366 return Py_BuildValue("kl", count, owner);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000367}
368
369PyDoc_STRVAR(rlock_release_save_doc,
370"_release_save() -> tuple\n\
371\n\
372For internal use by `threading.Condition`.");
373
374
375static PyObject *
376rlock_is_owned(rlockobject *self)
377{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000378 long tid = PyThread_get_thread_ident();
379
380 if (self->rlock_count > 0 && self->rlock_owner == tid) {
381 Py_RETURN_TRUE;
382 }
383 Py_RETURN_FALSE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000384}
385
386PyDoc_STRVAR(rlock_is_owned_doc,
387"_is_owned() -> bool\n\
388\n\
389For internal use by `threading.Condition`.");
390
391static PyObject *
392rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
393{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000394 rlockobject *self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 self = (rlockobject *) type->tp_alloc(type, 0);
397 if (self != NULL) {
398 self->rlock_lock = PyThread_allocate_lock();
399 if (self->rlock_lock == NULL) {
400 type->tp_free(self);
401 PyErr_SetString(ThreadError, "can't allocate lock");
402 return NULL;
403 }
404 self->in_weakreflist = NULL;
405 self->rlock_owner = 0;
406 self->rlock_count = 0;
407 }
Antoine Pitrou434736a2009-11-10 18:46:01 +0000408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000409 return (PyObject *) self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000410}
411
412static PyObject *
413rlock_repr(rlockobject *self)
414{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000415 return PyUnicode_FromFormat("<%s owner=%ld count=%lu>",
416 Py_TYPE(self)->tp_name, self->rlock_owner, self->rlock_count);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000417}
418
419
420static PyMethodDef rlock_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 {"acquire", (PyCFunction)rlock_acquire,
422 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
423 {"release", (PyCFunction)rlock_release,
424 METH_NOARGS, rlock_release_doc},
425 {"_is_owned", (PyCFunction)rlock_is_owned,
426 METH_NOARGS, rlock_is_owned_doc},
427 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
428 METH_O, rlock_acquire_restore_doc},
429 {"_release_save", (PyCFunction)rlock_release_save,
430 METH_NOARGS, rlock_release_save_doc},
431 {"__enter__", (PyCFunction)rlock_acquire,
432 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
433 {"__exit__", (PyCFunction)rlock_release,
434 METH_VARARGS, rlock_release_doc},
435 {NULL, NULL} /* sentinel */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000436};
437
438
439static PyTypeObject RLocktype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 PyVarObject_HEAD_INIT(&PyType_Type, 0)
441 "_thread.RLock", /*tp_name*/
442 sizeof(rlockobject), /*tp_size*/
443 0, /*tp_itemsize*/
444 /* methods */
445 (destructor)rlock_dealloc, /*tp_dealloc*/
446 0, /*tp_print*/
447 0, /*tp_getattr*/
448 0, /*tp_setattr*/
449 0, /*tp_reserved*/
450 (reprfunc)rlock_repr, /*tp_repr*/
451 0, /*tp_as_number*/
452 0, /*tp_as_sequence*/
453 0, /*tp_as_mapping*/
454 0, /*tp_hash*/
455 0, /*tp_call*/
456 0, /*tp_str*/
457 0, /*tp_getattro*/
458 0, /*tp_setattro*/
459 0, /*tp_as_buffer*/
460 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
461 0, /*tp_doc*/
462 0, /*tp_traverse*/
463 0, /*tp_clear*/
464 0, /*tp_richcompare*/
465 offsetof(rlockobject, in_weakreflist), /*tp_weaklistoffset*/
466 0, /*tp_iter*/
467 0, /*tp_iternext*/
468 rlock_methods, /*tp_methods*/
469 0, /* tp_members */
470 0, /* tp_getset */
471 0, /* tp_base */
472 0, /* tp_dict */
473 0, /* tp_descr_get */
474 0, /* tp_descr_set */
475 0, /* tp_dictoffset */
476 0, /* tp_init */
477 PyType_GenericAlloc, /* tp_alloc */
478 rlock_new /* tp_new */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000479};
480
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000481static lockobject *
482newlockobject(void)
483{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 lockobject *self;
485 self = PyObject_New(lockobject, &Locktype);
486 if (self == NULL)
487 return NULL;
488 self->lock_lock = PyThread_allocate_lock();
489 self->in_weakreflist = NULL;
490 if (self->lock_lock == NULL) {
491 Py_DECREF(self);
492 PyErr_SetString(ThreadError, "can't allocate lock");
493 return NULL;
494 }
495 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000496}
497
Jim Fultond15dc062004-07-14 19:11:50 +0000498/* Thread-local objects */
499
500#include "structmember.h"
501
502typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503 PyObject_HEAD
504 PyObject *key;
505 PyObject *args;
506 PyObject *kw;
507 PyObject *dict;
Jim Fultond15dc062004-07-14 19:11:50 +0000508} localobject;
509
Jim Fultond15dc062004-07-14 19:11:50 +0000510static PyObject *
511local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
512{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 localobject *self;
514 PyObject *tdict;
Jim Fultond15dc062004-07-14 19:11:50 +0000515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 if (type->tp_init == PyBaseObject_Type.tp_init
517 && ((args && PyObject_IsTrue(args))
518 || (kw && PyObject_IsTrue(kw)))) {
519 PyErr_SetString(PyExc_TypeError,
520 "Initialization arguments are not supported");
521 return NULL;
522 }
Jim Fultond15dc062004-07-14 19:11:50 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 self = (localobject *)type->tp_alloc(type, 0);
525 if (self == NULL)
526 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 Py_XINCREF(args);
529 self->args = args;
530 Py_XINCREF(kw);
531 self->kw = kw;
532 self->dict = NULL; /* making sure */
533 self->key = PyUnicode_FromFormat("thread.local.%p", self);
534 if (self->key == NULL)
535 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 self->dict = PyDict_New();
538 if (self->dict == NULL)
539 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 tdict = PyThreadState_GetDict();
542 if (tdict == NULL) {
543 PyErr_SetString(PyExc_SystemError,
544 "Couldn't get thread-state dictionary");
545 goto err;
546 }
Jim Fultond15dc062004-07-14 19:11:50 +0000547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 if (PyDict_SetItem(tdict, self->key, self->dict) < 0)
549 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000552
553 err:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 Py_DECREF(self);
555 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000556}
557
558static int
559local_traverse(localobject *self, visitproc visit, void *arg)
560{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 Py_VISIT(self->args);
562 Py_VISIT(self->kw);
563 Py_VISIT(self->dict);
564 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000565}
566
567static int
568local_clear(localobject *self)
569{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000570 Py_CLEAR(self->args);
571 Py_CLEAR(self->kw);
572 Py_CLEAR(self->dict);
573 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000574}
575
576static void
577local_dealloc(localobject *self)
578{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 PyThreadState *tstate;
580 if (self->key
581 && (tstate = PyThreadState_Get())
582 && tstate->interp) {
583 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
584 tstate;
585 tstate = PyThreadState_Next(tstate))
586 if (tstate->dict &&
587 PyDict_GetItem(tstate->dict, self->key))
588 PyDict_DelItem(tstate->dict, self->key);
589 }
Jim Fultond15dc062004-07-14 19:11:50 +0000590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 Py_XDECREF(self->key);
592 local_clear(self);
593 Py_TYPE(self)->tp_free((PyObject*)self);
Jim Fultond15dc062004-07-14 19:11:50 +0000594}
595
596static PyObject *
597_ldict(localobject *self)
598{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 PyObject *tdict, *ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 tdict = PyThreadState_GetDict();
602 if (tdict == NULL) {
603 PyErr_SetString(PyExc_SystemError,
604 "Couldn't get thread-state dictionary");
605 return NULL;
606 }
Jim Fultond15dc062004-07-14 19:11:50 +0000607
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 ldict = PyDict_GetItem(tdict, self->key);
609 if (ldict == NULL) {
610 ldict = PyDict_New(); /* we own ldict */
Jim Fultond15dc062004-07-14 19:11:50 +0000611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 if (ldict == NULL)
613 return NULL;
614 else {
615 int i = PyDict_SetItem(tdict, self->key, ldict);
616 Py_DECREF(ldict); /* now ldict is borrowed */
617 if (i < 0)
618 return NULL;
619 }
Jim Fultond15dc062004-07-14 19:11:50 +0000620
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 Py_CLEAR(self->dict);
622 Py_INCREF(ldict);
623 self->dict = ldict; /* still borrowed */
Jim Fultond15dc062004-07-14 19:11:50 +0000624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
626 Py_TYPE(self)->tp_init((PyObject*)self,
627 self->args, self->kw) < 0) {
628 /* we need to get rid of ldict from thread so
629 we create a new one the next time we do an attr
630 acces */
631 PyDict_DelItem(tdict, self->key);
632 return NULL;
633 }
Benjamin Peterson8a250ae2008-06-30 23:30:24 +0000634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000635 }
Jim Fultond15dc062004-07-14 19:11:50 +0000636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 /* The call to tp_init above may have caused another thread to run.
638 Install our ldict again. */
639 if (self->dict != ldict) {
640 Py_CLEAR(self->dict);
641 Py_INCREF(ldict);
642 self->dict = ldict;
643 }
644
645 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000646}
647
Jim Fultond15dc062004-07-14 19:11:50 +0000648static int
649local_setattro(localobject *self, PyObject *name, PyObject *v)
650{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 PyObject *ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 ldict = _ldict(self);
654 if (ldict == NULL)
655 return -1;
656
657 return PyObject_GenericSetAttr((PyObject *)self, name, v);
Jim Fultond15dc062004-07-14 19:11:50 +0000658}
659
660static PyObject *
661local_getdict(localobject *self, void *closure)
662{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 if (self->dict == NULL) {
664 PyErr_SetString(PyExc_AttributeError, "__dict__");
665 return NULL;
666 }
Jim Fultond15dc062004-07-14 19:11:50 +0000667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 Py_INCREF(self->dict);
669 return self->dict;
Jim Fultond15dc062004-07-14 19:11:50 +0000670}
671
672static PyGetSetDef local_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 {"__dict__", (getter)local_getdict, (setter)NULL,
674 "Local-data dictionary", NULL},
675 {NULL} /* Sentinel */
Jim Fultond15dc062004-07-14 19:11:50 +0000676};
677
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000678static PyObject *local_getattro(localobject *, PyObject *);
679
Jim Fultond15dc062004-07-14 19:11:50 +0000680static PyTypeObject localtype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 PyVarObject_HEAD_INIT(NULL, 0)
682 /* tp_name */ "_thread._local",
683 /* tp_basicsize */ sizeof(localobject),
684 /* tp_itemsize */ 0,
685 /* tp_dealloc */ (destructor)local_dealloc,
686 /* tp_print */ 0,
687 /* tp_getattr */ 0,
688 /* tp_setattr */ 0,
689 /* tp_reserved */ 0,
690 /* tp_repr */ 0,
691 /* tp_as_number */ 0,
692 /* tp_as_sequence */ 0,
693 /* tp_as_mapping */ 0,
694 /* tp_hash */ 0,
695 /* tp_call */ 0,
696 /* tp_str */ 0,
697 /* tp_getattro */ (getattrofunc)local_getattro,
698 /* tp_setattro */ (setattrofunc)local_setattro,
699 /* tp_as_buffer */ 0,
700 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
701 /* tp_doc */ "Thread-local data",
702 /* tp_traverse */ (traverseproc)local_traverse,
703 /* tp_clear */ (inquiry)local_clear,
704 /* tp_richcompare */ 0,
705 /* tp_weaklistoffset */ 0,
706 /* tp_iter */ 0,
707 /* tp_iternext */ 0,
708 /* tp_methods */ 0,
709 /* tp_members */ 0,
710 /* tp_getset */ local_getset,
711 /* tp_base */ 0,
712 /* tp_dict */ 0, /* internal use */
713 /* tp_descr_get */ 0,
714 /* tp_descr_set */ 0,
715 /* tp_dictoffset */ offsetof(localobject, dict),
716 /* tp_init */ 0,
717 /* tp_alloc */ 0,
718 /* tp_new */ local_new,
719 /* tp_free */ 0, /* Low-level free-mem routine */
720 /* tp_is_gc */ 0, /* For PyObject_IS_GC */
Jim Fultond15dc062004-07-14 19:11:50 +0000721};
722
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000723static PyObject *
724local_getattro(localobject *self, PyObject *name)
725{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 PyObject *ldict, *value;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 ldict = _ldict(self);
729 if (ldict == NULL)
730 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000731
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 if (Py_TYPE(self) != &localtype)
733 /* use generic lookup for subtypes */
734 return PyObject_GenericGetAttr((PyObject *)self, name);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 /* Optimization: just look in dict ourselves */
737 value = PyDict_GetItem(ldict, name);
738 if (value == NULL)
739 /* Fall back on generic to get __class__ and __dict__ */
740 return PyObject_GenericGetAttr((PyObject *)self, name);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 Py_INCREF(value);
743 return value;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000744}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000745
746/* Module functions */
747
Guido van Rossuma027efa1997-05-05 20:56:21 +0000748struct bootstate {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 PyInterpreterState *interp;
750 PyObject *func;
751 PyObject *args;
752 PyObject *keyw;
753 PyThreadState *tstate;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000754};
755
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000756static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000757t_bootstrap(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000758{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000759 struct bootstate *boot = (struct bootstate *) boot_raw;
760 PyThreadState *tstate;
761 PyObject *res;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 tstate = boot->tstate;
764 tstate->thread_id = PyThread_get_thread_ident();
765 _PyThreadState_Init(tstate);
766 PyEval_AcquireThread(tstate);
767 nb_threads++;
768 res = PyEval_CallObjectWithKeywords(
769 boot->func, boot->args, boot->keyw);
770 if (res == NULL) {
771 if (PyErr_ExceptionMatches(PyExc_SystemExit))
772 PyErr_Clear();
773 else {
774 PyObject *file;
775 PySys_WriteStderr(
776 "Unhandled exception in thread started by ");
777 file = PySys_GetObject("stderr");
778 if (file != NULL && file != Py_None)
779 PyFile_WriteObject(boot->func, file, 0);
780 else
781 PyObject_Print(boot->func, stderr, 0);
782 PySys_WriteStderr("\n");
783 PyErr_PrintEx(0);
784 }
785 }
786 else
787 Py_DECREF(res);
788 Py_DECREF(boot->func);
789 Py_DECREF(boot->args);
790 Py_XDECREF(boot->keyw);
791 PyMem_DEL(boot_raw);
792 nb_threads--;
793 PyThreadState_Clear(tstate);
794 PyThreadState_DeleteCurrent();
795 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000796}
797
Barry Warsawd0c10421996-12-17 00:05:22 +0000798static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000799thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 PyObject *func, *args, *keyw = NULL;
802 struct bootstate *boot;
803 long ident;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000804
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000805 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
806 &func, &args, &keyw))
807 return NULL;
808 if (!PyCallable_Check(func)) {
809 PyErr_SetString(PyExc_TypeError,
810 "first arg must be callable");
811 return NULL;
812 }
813 if (!PyTuple_Check(args)) {
814 PyErr_SetString(PyExc_TypeError,
815 "2nd arg must be a tuple");
816 return NULL;
817 }
818 if (keyw != NULL && !PyDict_Check(keyw)) {
819 PyErr_SetString(PyExc_TypeError,
820 "optional 3rd arg must be a dictionary");
821 return NULL;
822 }
823 boot = PyMem_NEW(struct bootstate, 1);
824 if (boot == NULL)
825 return PyErr_NoMemory();
826 boot->interp = PyThreadState_GET()->interp;
827 boot->func = func;
828 boot->args = args;
829 boot->keyw = keyw;
830 boot->tstate = _PyThreadState_Prealloc(boot->interp);
831 if (boot->tstate == NULL) {
832 PyMem_DEL(boot);
833 return PyErr_NoMemory();
834 }
835 Py_INCREF(func);
836 Py_INCREF(args);
837 Py_XINCREF(keyw);
838 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
839 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
840 if (ident == -1) {
841 PyErr_SetString(ThreadError, "can't start new thread");
842 Py_DECREF(func);
843 Py_DECREF(args);
844 Py_XDECREF(keyw);
845 PyThreadState_Clear(boot->tstate);
846 PyMem_DEL(boot);
847 return NULL;
848 }
849 return PyLong_FromLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000850}
851
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000852PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +0000853"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000854(start_new() is an obsolete synonym)\n\
855\n\
Guido van Rossum3c288632001-10-16 21:13:49 +0000856Start a new thread and return its identifier. The thread will call the\n\
857function with positional arguments from the tuple args and keyword arguments\n\
858taken from the optional dictionary kwargs. The thread exits when the\n\
859function returns; the return value is ignored. The thread will also exit\n\
860when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000861printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000862
Barry Warsawd0c10421996-12-17 00:05:22 +0000863static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000864thread_PyThread_exit_thread(PyObject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000865{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000866 PyErr_SetNone(PyExc_SystemExit);
867 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000868}
869
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000870PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000871"exit()\n\
Guido van Rossum65d5b571998-12-21 19:32:43 +0000872(PyThread_exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000873\n\
874This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000875thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000876
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000877static PyObject *
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +0000878thread_PyThread_interrupt_main(PyObject * self)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000879{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000880 PyErr_SetInterrupt();
881 Py_INCREF(Py_None);
882 return Py_None;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000883}
884
885PyDoc_STRVAR(interrupt_doc,
886"interrupt_main()\n\
887\n\
888Raise a KeyboardInterrupt in the main thread.\n\
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +0000889A subthread can use this function to interrupt the main thread."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000890);
891
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000892static lockobject *newlockobject(void);
893
Barry Warsawd0c10421996-12-17 00:05:22 +0000894static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000895thread_PyThread_allocate_lock(PyObject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000896{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000897 return (PyObject *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000898}
899
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000900PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000901"allocate_lock() -> lock object\n\
902(allocate() is an obsolete synonym)\n\
903\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000904Create a new lock object. See LockType.__doc__ for information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000905
Barry Warsawd0c10421996-12-17 00:05:22 +0000906static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000907thread_get_ident(PyObject *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000908{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000909 long ident;
910 ident = PyThread_get_thread_ident();
911 if (ident == -1) {
912 PyErr_SetString(ThreadError, "no current thread ident");
913 return NULL;
914 }
915 return PyLong_FromLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000916}
917
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000918PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000919"get_ident() -> integer\n\
920\n\
921Return a non-zero integer that uniquely identifies the current thread\n\
922amongst other threads that exist simultaneously.\n\
923This may be used to identify per-thread resources.\n\
924Even though on some platforms threads identities may appear to be\n\
925allocated consecutive numbers starting at 1, this behavior should not\n\
926be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000927A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000928
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000929static PyObject *
Antoine Pitrou65c9c642009-10-30 17:25:12 +0000930thread__count(PyObject *self)
931{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 return PyLong_FromLong(nb_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +0000933}
934
935PyDoc_STRVAR(_count_doc,
936"_count() -> integer\n\
937\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +0000938\
939Return the number of currently running Python threads, excluding \n\
940the main thread. The returned number comprises all threads created\n\
941through `start_new_thread()` as well as `threading.Thread`, and not\n\
942yet finished.\n\
943\n\
944This function is meant for internal and specialized purposes only.\n\
945In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +0000946
947static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000948thread_stack_size(PyObject *self, PyObject *args)
949{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000950 size_t old_size;
951 Py_ssize_t new_size = 0;
952 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000954 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
955 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000956
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000957 if (new_size < 0) {
958 PyErr_SetString(PyExc_ValueError,
959 "size must be 0 or a positive value");
960 return NULL;
961 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000962
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000963 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000965 rc = PyThread_set_stacksize((size_t) new_size);
966 if (rc == -1) {
967 PyErr_Format(PyExc_ValueError,
968 "size not valid: %zd bytes",
969 new_size);
970 return NULL;
971 }
972 if (rc == -2) {
973 PyErr_SetString(ThreadError,
974 "setting stack size not supported");
975 return NULL;
976 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000977
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000978 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000979}
980
981PyDoc_STRVAR(stack_size_doc,
982"stack_size([size]) -> size\n\
983\n\
984Return the thread stack size used when creating new threads. The\n\
985optional size argument specifies the stack size (in bytes) to be used\n\
986for subsequently created threads, and must be 0 (use platform or\n\
987configured default) or a positive integer value of at least 32,768 (32k).\n\
988If changing the thread stack size is unsupported, a ThreadError\n\
989exception is raised. If the specified size is invalid, a ValueError\n\
990exception is raised, and the stack size is unmodified. 32k bytes\n\
991 currently the minimum supported stack size value to guarantee\n\
992sufficient stack space for the interpreter itself.\n\
993\n\
994Note that some platforms may have particular restrictions on values for\n\
995the stack size, such as requiring a minimum stack size larger than 32kB or\n\
996requiring allocation in multiples of the system memory page size\n\
997- platform documentation should be referred to for more information\n\
998(4kB pages are common; using multiples of 4096 for the stack size is\n\
999the suggested approach in the absence of more specific information).");
1000
Barry Warsawd0c10421996-12-17 00:05:22 +00001001static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
1003 METH_VARARGS,
1004 start_new_doc},
1005 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
1006 METH_VARARGS,
1007 start_new_doc},
1008 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
1009 METH_NOARGS, allocate_doc},
1010 {"allocate", (PyCFunction)thread_PyThread_allocate_lock,
1011 METH_NOARGS, allocate_doc},
1012 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread,
1013 METH_NOARGS, exit_doc},
1014 {"exit", (PyCFunction)thread_PyThread_exit_thread,
1015 METH_NOARGS, exit_doc},
1016 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1017 METH_NOARGS, interrupt_doc},
1018 {"get_ident", (PyCFunction)thread_get_ident,
1019 METH_NOARGS, get_ident_doc},
1020 {"_count", (PyCFunction)thread__count,
1021 METH_NOARGS, _count_doc},
1022 {"stack_size", (PyCFunction)thread_stack_size,
1023 METH_VARARGS,
1024 stack_size_doc},
1025 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001026};
1027
1028
1029/* Initialization function */
1030
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001031PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001032"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001033The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001034
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001035PyDoc_STRVAR(lock_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001036"A lock object is a synchronization primitive. To create a lock,\n\
Guido van Rossum65d5b571998-12-21 19:32:43 +00001037call the PyThread_allocate_lock() function. Methods are:\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001038\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001039acquire() -- lock the lock, possibly blocking until it can be obtained\n\
1040release() -- unlock of the lock\n\
1041locked() -- test whether the lock is currently locked\n\
1042\n\
1043A lock is not owned by the thread that locked it; another thread may\n\
1044unlock it. A thread attempting to lock a lock that it has already locked\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001045will block until another thread unlocks it. Deadlocks may ensue.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001046
Martin v. Löwis1a214512008-06-11 05:26:20 +00001047static struct PyModuleDef threadmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001048 PyModuleDef_HEAD_INIT,
1049 "_thread",
1050 thread_doc,
1051 -1,
1052 thread_methods,
1053 NULL,
1054 NULL,
1055 NULL,
1056 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001057};
1058
1059
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001060PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001061PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001063 PyObject *m, *d, *timeout_max;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001065 /* Initialize types: */
1066 if (PyType_Ready(&localtype) < 0)
1067 return NULL;
1068 if (PyType_Ready(&Locktype) < 0)
1069 return NULL;
1070 if (PyType_Ready(&RLocktype) < 0)
1071 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001073 /* Create the module and add the functions */
1074 m = PyModule_Create(&threadmodule);
1075 if (m == NULL)
1076 return NULL;
Antoine Pitrou7c3e5772010-04-14 15:44:10 +00001077
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001078 timeout_max = PyFloat_FromDouble(PY_TIMEOUT_MAX / 1000000);
1079 if (!timeout_max)
1080 return NULL;
1081 if (PyModule_AddObject(m, "TIMEOUT_MAX", timeout_max) < 0)
1082 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001084 /* Add a symbolic constant */
1085 d = PyModule_GetDict(m);
1086 ThreadError = PyErr_NewException("_thread.error", NULL, NULL);
1087 PyDict_SetItemString(d, "error", ThreadError);
1088 Locktype.tp_doc = lock_doc;
1089 Py_INCREF(&Locktype);
1090 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
Antoine Pitrou434736a2009-11-10 18:46:01 +00001091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001092 Py_INCREF(&RLocktype);
1093 if (PyModule_AddObject(m, "RLock", (PyObject *)&RLocktype) < 0)
1094 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +00001095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 Py_INCREF(&localtype);
1097 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
1098 return NULL;
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001100 nb_threads = 0;
1101
1102 /* Initialize the C thread library */
1103 PyThread_init_thread();
1104 return m;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001105}