Get rid of some warnings.
[python.git] / Modules / threadmodule.c
blob9a6c5d80573576723be483679a49ee8f143ecc82
2 /* Thread module */
3 /* Interface to Sjoerd's portable C thread library */
5 #include "Python.h"
7 #ifndef WITH_THREAD
8 #error "Error! The rest of Python is not compiled with thread support."
9 #error "Rerun configure, adding a --with-threads option."
10 #error "Then run `make clean' followed by `make'."
11 #endif
13 #include "pythread.h"
15 static PyObject *ThreadError;
18 /* Lock objects */
20 typedef struct {
21 PyObject_HEAD
22 PyThread_type_lock lock_lock;
23 } lockobject;
25 static PyTypeObject Locktype;
27 static lockobject *
28 newlockobject(void)
30 lockobject *self;
31 self = PyObject_New(lockobject, &Locktype);
32 if (self == NULL)
33 return NULL;
34 self->lock_lock = PyThread_allocate_lock();
35 if (self->lock_lock == NULL) {
36 PyObject_Del(self);
37 self = NULL;
38 PyErr_SetString(ThreadError, "can't allocate lock");
40 return self;
43 static void
44 lock_dealloc(lockobject *self)
46 /* Unlock the lock so it's safe to free it */
47 PyThread_acquire_lock(self->lock_lock, 0);
48 PyThread_release_lock(self->lock_lock);
50 PyThread_free_lock(self->lock_lock);
51 PyObject_Del(self);
54 static PyObject *
55 lock_PyThread_acquire_lock(lockobject *self, PyObject *args)
57 int i = 1;
59 if (!PyArg_ParseTuple(args, "|i:acquire", &i))
60 return NULL;
62 Py_BEGIN_ALLOW_THREADS
63 i = PyThread_acquire_lock(self->lock_lock, i);
64 Py_END_ALLOW_THREADS
66 return PyBool_FromLong((long)i);
69 PyDoc_STRVAR(acquire_doc,
70 "acquire([wait]) -> None or bool\n\
71 (acquire_lock() is an obsolete synonym)\n\
72 \n\
73 Lock the lock. Without argument, this blocks if the lock is already\n\
74 locked (even by the same thread), waiting for another thread to release\n\
75 the lock, and return None once the lock is acquired.\n\
76 With an argument, this will only block if the argument is true,\n\
77 and the return value reflects whether the lock is acquired.\n\
78 The blocking operation is not interruptible.");
80 static PyObject *
81 lock_PyThread_release_lock(lockobject *self)
83 /* Sanity check: the lock must be locked */
84 if (PyThread_acquire_lock(self->lock_lock, 0)) {
85 PyThread_release_lock(self->lock_lock);
86 PyErr_SetString(ThreadError, "release unlocked lock");
87 return NULL;
90 PyThread_release_lock(self->lock_lock);
91 Py_INCREF(Py_None);
92 return Py_None;
95 PyDoc_STRVAR(release_doc,
96 "release()\n\
97 (release_lock() is an obsolete synonym)\n\
98 \n\
99 Release the lock, allowing another thread that is blocked waiting for\n\
100 the lock to acquire the lock. The lock must be in the locked state,\n\
101 but it needn't be locked by the same thread that unlocks it.");
103 static PyObject *
104 lock_locked_lock(lockobject *self)
106 if (PyThread_acquire_lock(self->lock_lock, 0)) {
107 PyThread_release_lock(self->lock_lock);
108 return PyBool_FromLong(0L);
110 return PyBool_FromLong(1L);
113 PyDoc_STRVAR(locked_doc,
114 "locked() -> bool\n\
115 (locked_lock() is an obsolete synonym)\n\
117 Return whether the lock is in the locked state.");
119 static PyObject *
120 lock_context(lockobject *self)
122 Py_INCREF(self);
123 return (PyObject *)self;
126 static PyMethodDef lock_methods[] = {
127 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
128 METH_VARARGS, acquire_doc},
129 {"acquire", (PyCFunction)lock_PyThread_acquire_lock,
130 METH_VARARGS, acquire_doc},
131 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
132 METH_NOARGS, release_doc},
133 {"release", (PyCFunction)lock_PyThread_release_lock,
134 METH_NOARGS, release_doc},
135 {"locked_lock", (PyCFunction)lock_locked_lock,
136 METH_NOARGS, locked_doc},
137 {"locked", (PyCFunction)lock_locked_lock,
138 METH_NOARGS, locked_doc},
139 {"__context__", (PyCFunction)lock_context,
140 METH_NOARGS, PyDoc_STR("__context__() -> self.")},
141 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock,
142 METH_VARARGS, acquire_doc},
143 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
144 METH_VARARGS, release_doc},
145 {NULL, NULL} /* sentinel */
148 static PyObject *
149 lock_getattr(lockobject *self, char *name)
151 return Py_FindMethod(lock_methods, (PyObject *)self, name);
154 static PyTypeObject Locktype = {
155 PyObject_HEAD_INIT(&PyType_Type)
156 0, /*ob_size*/
157 "thread.lock", /*tp_name*/
158 sizeof(lockobject), /*tp_size*/
159 0, /*tp_itemsize*/
160 /* methods */
161 (destructor)lock_dealloc, /*tp_dealloc*/
162 0, /*tp_print*/
163 (getattrfunc)lock_getattr, /*tp_getattr*/
164 0, /*tp_setattr*/
165 0, /*tp_compare*/
166 0, /*tp_repr*/
169 /* Thread-local objects */
171 #include "structmember.h"
173 typedef struct {
174 PyObject_HEAD
175 PyObject *key;
176 PyObject *args;
177 PyObject *kw;
178 PyObject *dict;
179 } localobject;
181 static PyTypeObject localtype;
183 static PyObject *
184 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
186 localobject *self;
187 PyObject *tdict;
189 if (type->tp_init == PyBaseObject_Type.tp_init
190 && ((args && PyObject_IsTrue(args))
191 || (kw && PyObject_IsTrue(kw)))) {
192 PyErr_SetString(PyExc_TypeError,
193 "Initialization arguments are not supported");
194 return NULL;
197 self = (localobject *)type->tp_alloc(type, 0);
198 if (self == NULL)
199 return NULL;
201 Py_XINCREF(args);
202 self->args = args;
203 Py_XINCREF(kw);
204 self->kw = kw;
205 self->dict = NULL; /* making sure */
206 self->key = PyString_FromFormat("thread.local.%p", self);
207 if (self->key == NULL)
208 goto err;
210 self->dict = PyDict_New();
211 if (self->dict == NULL)
212 goto err;
214 tdict = PyThreadState_GetDict();
215 if (tdict == NULL) {
216 PyErr_SetString(PyExc_SystemError,
217 "Couldn't get thread-state dictionary");
218 goto err;
221 if (PyDict_SetItem(tdict, self->key, self->dict) < 0)
222 goto err;
224 return (PyObject *)self;
226 err:
227 Py_DECREF(self);
228 return NULL;
231 static int
232 local_traverse(localobject *self, visitproc visit, void *arg)
234 Py_VISIT(self->args);
235 Py_VISIT(self->kw);
236 Py_VISIT(self->dict);
237 return 0;
240 static int
241 local_clear(localobject *self)
243 Py_CLEAR(self->key);
244 Py_CLEAR(self->args);
245 Py_CLEAR(self->kw);
246 Py_CLEAR(self->dict);
247 return 0;
250 static void
251 local_dealloc(localobject *self)
253 PyThreadState *tstate;
254 if (self->key
255 && (tstate = PyThreadState_Get())
256 && tstate->interp) {
257 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
258 tstate;
259 tstate = PyThreadState_Next(tstate))
260 if (tstate->dict &&
261 PyDict_GetItem(tstate->dict, self->key))
262 PyDict_DelItem(tstate->dict, self->key);
265 local_clear(self);
266 self->ob_type->tp_free((PyObject*)self);
269 static PyObject *
270 _ldict(localobject *self)
272 PyObject *tdict, *ldict;
274 tdict = PyThreadState_GetDict();
275 if (tdict == NULL) {
276 PyErr_SetString(PyExc_SystemError,
277 "Couldn't get thread-state dictionary");
278 return NULL;
281 ldict = PyDict_GetItem(tdict, self->key);
282 if (ldict == NULL) {
283 ldict = PyDict_New(); /* we own ldict */
285 if (ldict == NULL)
286 return NULL;
287 else {
288 int i = PyDict_SetItem(tdict, self->key, ldict);
289 Py_DECREF(ldict); /* now ldict is borrowed */
290 if (i < 0)
291 return NULL;
294 Py_CLEAR(self->dict);
295 Py_INCREF(ldict);
296 self->dict = ldict; /* still borrowed */
298 if (self->ob_type->tp_init != PyBaseObject_Type.tp_init &&
299 self->ob_type->tp_init((PyObject*)self,
300 self->args, self->kw) < 0) {
301 /* we need to get rid of ldict from thread so
302 we create a new one the next time we do an attr
303 acces */
304 PyDict_DelItem(tdict, self->key);
305 return NULL;
309 else if (self->dict != ldict) {
310 Py_CLEAR(self->dict);
311 Py_INCREF(ldict);
312 self->dict = ldict;
315 return ldict;
318 static PyObject *
319 local_getattro(localobject *self, PyObject *name)
321 PyObject *ldict, *value;
323 ldict = _ldict(self);
324 if (ldict == NULL)
325 return NULL;
327 if (self->ob_type != &localtype)
328 /* use generic lookup for subtypes */
329 return PyObject_GenericGetAttr((PyObject *)self, name);
331 /* Optimization: just look in dict ourselves */
332 value = PyDict_GetItem(ldict, name);
333 if (value == NULL)
334 /* Fall back on generic to get __class__ and __dict__ */
335 return PyObject_GenericGetAttr((PyObject *)self, name);
337 Py_INCREF(value);
338 return value;
341 static int
342 local_setattro(localobject *self, PyObject *name, PyObject *v)
344 PyObject *ldict;
346 ldict = _ldict(self);
347 if (ldict == NULL)
348 return -1;
350 return PyObject_GenericSetAttr((PyObject *)self, name, v);
353 static PyObject *
354 local_getdict(localobject *self, void *closure)
356 if (self->dict == NULL) {
357 PyErr_SetString(PyExc_AttributeError, "__dict__");
358 return NULL;
361 Py_INCREF(self->dict);
362 return self->dict;
365 static PyGetSetDef local_getset[] = {
366 {"__dict__", (getter)local_getdict, (setter)NULL,
367 "Local-data dictionary", NULL},
368 {NULL} /* Sentinel */
371 static PyTypeObject localtype = {
372 PyObject_HEAD_INIT(NULL)
373 /* ob_size */ 0,
374 /* tp_name */ "thread._local",
375 /* tp_basicsize */ sizeof(localobject),
376 /* tp_itemsize */ 0,
377 /* tp_dealloc */ (destructor)local_dealloc,
378 /* tp_print */ (printfunc)0,
379 /* tp_getattr */ (getattrfunc)0,
380 /* tp_setattr */ (setattrfunc)0,
381 /* tp_compare */ (cmpfunc)0,
382 /* tp_repr */ (reprfunc)0,
383 /* tp_as_number */ 0,
384 /* tp_as_sequence */ 0,
385 /* tp_as_mapping */ 0,
386 /* tp_hash */ (hashfunc)0,
387 /* tp_call */ (ternaryfunc)0,
388 /* tp_str */ (reprfunc)0,
389 /* tp_getattro */ (getattrofunc)local_getattro,
390 /* tp_setattro */ (setattrofunc)local_setattro,
391 /* tp_as_buffer */ 0,
392 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
393 /* tp_doc */ "Thread-local data",
394 /* tp_traverse */ (traverseproc)local_traverse,
395 /* tp_clear */ (inquiry)local_clear,
396 /* tp_richcompare */ (richcmpfunc)0,
397 /* tp_weaklistoffset */ (long)0,
398 /* tp_iter */ (getiterfunc)0,
399 /* tp_iternext */ (iternextfunc)0,
400 /* tp_methods */ 0,
401 /* tp_members */ 0,
402 /* tp_getset */ local_getset,
403 /* tp_base */ 0,
404 /* tp_dict */ 0, /* internal use */
405 /* tp_descr_get */ (descrgetfunc)0,
406 /* tp_descr_set */ (descrsetfunc)0,
407 /* tp_dictoffset */ offsetof(localobject, dict),
408 /* tp_init */ (initproc)0,
409 /* tp_alloc */ (allocfunc)0,
410 /* tp_new */ (newfunc)local_new,
411 /* tp_free */ 0, /* Low-level free-mem routine */
412 /* tp_is_gc */ (inquiry)0, /* For PyObject_IS_GC */
416 /* Module functions */
418 struct bootstate {
419 PyInterpreterState *interp;
420 PyObject *func;
421 PyObject *args;
422 PyObject *keyw;
425 static void
426 t_bootstrap(void *boot_raw)
428 struct bootstate *boot = (struct bootstate *) boot_raw;
429 PyThreadState *tstate;
430 PyObject *res;
432 tstate = PyThreadState_New(boot->interp);
434 PyEval_AcquireThread(tstate);
435 res = PyEval_CallObjectWithKeywords(
436 boot->func, boot->args, boot->keyw);
437 if (res == NULL) {
438 if (PyErr_ExceptionMatches(PyExc_SystemExit))
439 PyErr_Clear();
440 else {
441 PyObject *file;
442 PySys_WriteStderr(
443 "Unhandled exception in thread started by ");
444 file = PySys_GetObject("stderr");
445 if (file)
446 PyFile_WriteObject(boot->func, file, 0);
447 else
448 PyObject_Print(boot->func, stderr, 0);
449 PySys_WriteStderr("\n");
450 PyErr_PrintEx(0);
453 else
454 Py_DECREF(res);
455 Py_DECREF(boot->func);
456 Py_DECREF(boot->args);
457 Py_XDECREF(boot->keyw);
458 PyMem_DEL(boot_raw);
459 PyThreadState_Clear(tstate);
460 PyThreadState_DeleteCurrent();
461 PyThread_exit_thread();
464 static PyObject *
465 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
467 PyObject *func, *args, *keyw = NULL;
468 struct bootstate *boot;
469 long ident;
471 if (!PyArg_ParseTuple(fargs, "OO|O:start_new_thread", &func, &args, &keyw))
472 return NULL;
473 if (!PyCallable_Check(func)) {
474 PyErr_SetString(PyExc_TypeError,
475 "first arg must be callable");
476 return NULL;
478 if (!PyTuple_Check(args)) {
479 PyErr_SetString(PyExc_TypeError,
480 "2nd arg must be a tuple");
481 return NULL;
483 if (keyw != NULL && !PyDict_Check(keyw)) {
484 PyErr_SetString(PyExc_TypeError,
485 "optional 3rd arg must be a dictionary");
486 return NULL;
488 boot = PyMem_NEW(struct bootstate, 1);
489 if (boot == NULL)
490 return PyErr_NoMemory();
491 boot->interp = PyThreadState_GET()->interp;
492 boot->func = func;
493 boot->args = args;
494 boot->keyw = keyw;
495 Py_INCREF(func);
496 Py_INCREF(args);
497 Py_XINCREF(keyw);
498 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
499 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
500 if (ident == -1) {
501 PyErr_SetString(ThreadError, "can't start new thread");
502 Py_DECREF(func);
503 Py_DECREF(args);
504 Py_XDECREF(keyw);
505 PyMem_DEL(boot);
506 return NULL;
508 return PyInt_FromLong(ident);
511 PyDoc_STRVAR(start_new_doc,
512 "start_new_thread(function, args[, kwargs])\n\
513 (start_new() is an obsolete synonym)\n\
515 Start a new thread and return its identifier. The thread will call the\n\
516 function with positional arguments from the tuple args and keyword arguments\n\
517 taken from the optional dictionary kwargs. The thread exits when the\n\
518 function returns; the return value is ignored. The thread will also exit\n\
519 when the function raises an unhandled exception; a stack trace will be\n\
520 printed unless the exception is SystemExit.\n");
522 static PyObject *
523 thread_PyThread_exit_thread(PyObject *self)
525 PyErr_SetNone(PyExc_SystemExit);
526 return NULL;
529 PyDoc_STRVAR(exit_doc,
530 "exit()\n\
531 (PyThread_exit_thread() is an obsolete synonym)\n\
533 This is synonymous to ``raise SystemExit''. It will cause the current\n\
534 thread to exit silently unless the exception is caught.");
536 static PyObject *
537 thread_PyThread_interrupt_main(PyObject * self)
539 PyErr_SetInterrupt();
540 Py_INCREF(Py_None);
541 return Py_None;
544 PyDoc_STRVAR(interrupt_doc,
545 "interrupt_main()\n\
547 Raise a KeyboardInterrupt in the main thread.\n\
548 A subthread can use this function to interrupt the main thread."
551 #ifndef NO_EXIT_PROG
552 static PyObject *
553 thread_PyThread_exit_prog(PyObject *self, PyObject *args)
555 int sts;
556 if (!PyArg_ParseTuple(args, "i:exit_prog", &sts))
557 return NULL;
558 Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */
559 for (;;) { } /* Should not be reached */
561 #endif
563 static PyObject *
564 thread_PyThread_allocate_lock(PyObject *self)
566 return (PyObject *) newlockobject();
569 PyDoc_STRVAR(allocate_doc,
570 "allocate_lock() -> lock object\n\
571 (allocate() is an obsolete synonym)\n\
573 Create a new lock object. See LockType.__doc__ for information about locks.");
575 static PyObject *
576 thread_get_ident(PyObject *self)
578 long ident;
579 ident = PyThread_get_thread_ident();
580 if (ident == -1) {
581 PyErr_SetString(ThreadError, "no current thread ident");
582 return NULL;
584 return PyInt_FromLong(ident);
587 PyDoc_STRVAR(get_ident_doc,
588 "get_ident() -> integer\n\
590 Return a non-zero integer that uniquely identifies the current thread\n\
591 amongst other threads that exist simultaneously.\n\
592 This may be used to identify per-thread resources.\n\
593 Even though on some platforms threads identities may appear to be\n\
594 allocated consecutive numbers starting at 1, this behavior should not\n\
595 be relied upon, and the number should be seen purely as a magic cookie.\n\
596 A thread's identity may be reused for another thread after it exits.");
598 static PyMethodDef thread_methods[] = {
599 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
600 METH_VARARGS,
601 start_new_doc},
602 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
603 METH_VARARGS,
604 start_new_doc},
605 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
606 METH_NOARGS, allocate_doc},
607 {"allocate", (PyCFunction)thread_PyThread_allocate_lock,
608 METH_NOARGS, allocate_doc},
609 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread,
610 METH_NOARGS, exit_doc},
611 {"exit", (PyCFunction)thread_PyThread_exit_thread,
612 METH_NOARGS, exit_doc},
613 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
614 METH_NOARGS, interrupt_doc},
615 {"get_ident", (PyCFunction)thread_get_ident,
616 METH_NOARGS, get_ident_doc},
617 #ifndef NO_EXIT_PROG
618 {"exit_prog", (PyCFunction)thread_PyThread_exit_prog,
619 METH_VARARGS},
620 #endif
621 {NULL, NULL} /* sentinel */
625 /* Initialization function */
627 PyDoc_STRVAR(thread_doc,
628 "This module provides primitive operations to write multi-threaded programs.\n\
629 The 'threading' module provides a more convenient interface.");
631 PyDoc_STRVAR(lock_doc,
632 "A lock object is a synchronization primitive. To create a lock,\n\
633 call the PyThread_allocate_lock() function. Methods are:\n\
635 acquire() -- lock the lock, possibly blocking until it can be obtained\n\
636 release() -- unlock of the lock\n\
637 locked() -- test whether the lock is currently locked\n\
639 A lock is not owned by the thread that locked it; another thread may\n\
640 unlock it. A thread attempting to lock a lock that it has already locked\n\
641 will block until another thread unlocks it. Deadlocks may ensue.");
643 PyMODINIT_FUNC
644 initthread(void)
646 PyObject *m, *d;
648 /* Initialize types: */
649 if (PyType_Ready(&localtype) < 0)
650 return;
652 /* Create the module and add the functions */
653 m = Py_InitModule3("thread", thread_methods, thread_doc);
654 if (m == NULL)
655 return;
657 /* Add a symbolic constant */
658 d = PyModule_GetDict(m);
659 ThreadError = PyErr_NewException("thread.error", NULL, NULL);
660 PyDict_SetItemString(d, "error", ThreadError);
661 Locktype.tp_doc = lock_doc;
662 Py_INCREF(&Locktype);
663 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
665 Py_INCREF(&localtype);
666 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
667 return;
669 /* Initialize the C thread library */
670 PyThread_init_thread();