| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 1 |  | 
 | 2 | /* Thread module */ | 
 | 3 | /* Interface to Sjoerd's portable C thread library */ | 
 | 4 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 5 | #include "Python.h" | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 6 |  | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 7 | #ifndef WITH_THREAD | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 8 | #error "Error!  The rest of Python is not compiled with thread support." | 
 | 9 | #error "Rerun configure, adding a --with-thread option." | 
 | 10 | #error "Then run `make clean' followed by `make'." | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 11 | #endif | 
 | 12 |  | 
| Guido van Rossum | 49b5606 | 1998-10-01 20:42:43 +0000 | [diff] [blame] | 13 | #include "pythread.h" | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 14 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 15 | static PyObject *ThreadError; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 16 |  | 
 | 17 |  | 
 | 18 | /* Lock objects */ | 
 | 19 |  | 
 | 20 | typedef struct { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 21 | 	PyObject_HEAD | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 22 | 	PyThread_type_lock lock_lock; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 23 | } lockobject; | 
 | 24 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 25 | staticforward PyTypeObject Locktype; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 26 |  | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 27 | static lockobject * | 
| Thomas Wouters | f3f33dc | 2000-07-21 06:00:07 +0000 | [diff] [blame] | 28 | newlockobject(void) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 29 | { | 
 | 30 | 	lockobject *self; | 
| Guido van Rossum | b18618d | 2000-05-03 23:44:39 +0000 | [diff] [blame] | 31 | 	self = PyObject_New(lockobject, &Locktype); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 32 | 	if (self == NULL) | 
 | 33 | 		return NULL; | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 34 | 	self->lock_lock = PyThread_allocate_lock(); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 35 | 	if (self->lock_lock == NULL) { | 
| Guido van Rossum | b18618d | 2000-05-03 23:44:39 +0000 | [diff] [blame] | 36 | 		PyObject_Del(self); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 37 | 		self = NULL; | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 38 | 		PyErr_SetString(ThreadError, "can't allocate lock"); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 39 | 	} | 
 | 40 | 	return self; | 
 | 41 | } | 
 | 42 |  | 
 | 43 | static void | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 44 | lock_dealloc(lockobject *self) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 45 | { | 
 | 46 | 	/* Unlock the lock so it's safe to free it */ | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 47 | 	PyThread_acquire_lock(self->lock_lock, 0); | 
 | 48 | 	PyThread_release_lock(self->lock_lock); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 49 | 	 | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 50 | 	PyThread_free_lock(self->lock_lock); | 
| Guido van Rossum | b18618d | 2000-05-03 23:44:39 +0000 | [diff] [blame] | 51 | 	PyObject_Del(self); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 52 | } | 
 | 53 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 54 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 55 | lock_PyThread_acquire_lock(lockobject *self, PyObject *args) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 56 | { | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 57 | 	int i; | 
 | 58 |  | 
 | 59 | 	if (args != NULL) { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 60 | 		if (!PyArg_Parse(args, "i", &i)) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 61 | 			return NULL; | 
 | 62 | 	} | 
 | 63 | 	else | 
 | 64 | 		i = 1; | 
 | 65 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 66 | 	Py_BEGIN_ALLOW_THREADS | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 67 | 	i = PyThread_acquire_lock(self->lock_lock, i); | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 68 | 	Py_END_ALLOW_THREADS | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 69 |  | 
 | 70 | 	if (args == NULL) { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 71 | 		Py_INCREF(Py_None); | 
 | 72 | 		return Py_None; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 73 | 	} | 
 | 74 | 	else | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 75 | 		return PyInt_FromLong((long)i); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 76 | } | 
 | 77 |  | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 78 | static char acquire_doc[] = | 
 | 79 | "acquire([wait]) -> None or Boolean\n\ | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 80 | (PyThread_acquire_lock() is an obsolete synonym)\n\ | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 81 | \n\ | 
 | 82 | Lock the lock.  Without argument, this blocks if the lock is already\n\ | 
 | 83 | locked (even by the same thread), waiting for another thread to release\n\ | 
 | 84 | the lock, and return None when the lock is acquired.\n\ | 
 | 85 | With a Boolean argument, this will only block if the argument is true,\n\ | 
 | 86 | and the return value reflects whether the lock is acquired.\n\ | 
 | 87 | The blocking operation is not interruptible."; | 
 | 88 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 89 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 90 | lock_PyThread_release_lock(lockobject *self, PyObject *args) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 91 | { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 92 | 	if (!PyArg_NoArgs(args)) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 93 | 		return NULL; | 
 | 94 |  | 
 | 95 | 	/* Sanity check: the lock must be locked */ | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 96 | 	if (PyThread_acquire_lock(self->lock_lock, 0)) { | 
 | 97 | 		PyThread_release_lock(self->lock_lock); | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 98 | 		PyErr_SetString(ThreadError, "release unlocked lock"); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 99 | 		return NULL; | 
 | 100 | 	} | 
 | 101 |  | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 102 | 	PyThread_release_lock(self->lock_lock); | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 103 | 	Py_INCREF(Py_None); | 
 | 104 | 	return Py_None; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 105 | } | 
 | 106 |  | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 107 | static char release_doc[] = | 
 | 108 | "release()\n\ | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 109 | (PyThread_release_lock() is an obsolete synonym)\n\ | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 110 | \n\ | 
 | 111 | Release the lock, allowing another thread that is blocked waiting for\n\ | 
 | 112 | the lock to acquire the lock.  The lock must be in the locked state,\n\ | 
 | 113 | but it needn't be locked by the same thread that unlocks it."; | 
 | 114 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 115 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 116 | lock_locked_lock(lockobject *self, PyObject *args) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 117 | { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 118 | 	if (!PyArg_NoArgs(args)) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 119 | 		return NULL; | 
 | 120 |  | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 121 | 	if (PyThread_acquire_lock(self->lock_lock, 0)) { | 
 | 122 | 		PyThread_release_lock(self->lock_lock); | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 123 | 		return PyInt_FromLong(0L); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 124 | 	} | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 125 | 	return PyInt_FromLong(1L); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 126 | } | 
 | 127 |  | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 128 | static char locked_doc[] = | 
 | 129 | "locked() -> Boolean\n\ | 
 | 130 | (locked_lock() is an obsolete synonym)\n\ | 
 | 131 | \n\ | 
 | 132 | Return whether the lock is in the locked state."; | 
 | 133 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 134 | static PyMethodDef lock_methods[] = { | 
| Andrew M. Kuchling | a1abb72 | 2000-08-03 02:34:44 +0000 | [diff] [blame] | 135 | 	{"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,  | 
 | 136 | 	 METH_OLDARGS, acquire_doc}, | 
 | 137 | 	{"acquire",      (PyCFunction)lock_PyThread_acquire_lock,  | 
 | 138 | 	 METH_OLDARGS, acquire_doc}, | 
 | 139 | 	{"release_lock", (PyCFunction)lock_PyThread_release_lock,  | 
 | 140 | 	 METH_OLDARGS, release_doc}, | 
 | 141 | 	{"release",      (PyCFunction)lock_PyThread_release_lock,  | 
 | 142 | 	 METH_OLDARGS, release_doc}, | 
 | 143 | 	{"locked_lock",  (PyCFunction)lock_locked_lock,   | 
 | 144 | 	 METH_OLDARGS, locked_doc}, | 
 | 145 | 	{"locked",       (PyCFunction)lock_locked_lock,   | 
 | 146 | 	 METH_OLDARGS, locked_doc}, | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 147 | 	{NULL,           NULL}		/* sentinel */ | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 148 | }; | 
 | 149 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 150 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 151 | lock_getattr(lockobject *self, char *name) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 152 | { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 153 | 	return Py_FindMethod(lock_methods, (PyObject *)self, name); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 154 | } | 
 | 155 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 156 | static PyTypeObject Locktype = { | 
 | 157 | 	PyObject_HEAD_INIT(&PyType_Type) | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 158 | 	0,				/*ob_size*/ | 
 | 159 | 	"lock",				/*tp_name*/ | 
 | 160 | 	sizeof(lockobject),		/*tp_size*/ | 
 | 161 | 	0,				/*tp_itemsize*/ | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 162 | 	/* methods */ | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 163 | 	(destructor)lock_dealloc,	/*tp_dealloc*/ | 
 | 164 | 	0,				/*tp_print*/ | 
 | 165 | 	(getattrfunc)lock_getattr,	/*tp_getattr*/ | 
 | 166 | 	0,				/*tp_setattr*/ | 
 | 167 | 	0,				/*tp_compare*/ | 
 | 168 | 	0,				/*tp_repr*/ | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 169 | }; | 
 | 170 |  | 
 | 171 |  | 
 | 172 | /* Module functions */ | 
 | 173 |  | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 174 | struct bootstate { | 
 | 175 | 	PyInterpreterState *interp; | 
 | 176 | 	PyObject *func; | 
 | 177 | 	PyObject *args; | 
 | 178 | 	PyObject *keyw; | 
 | 179 | }; | 
 | 180 |  | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 181 | static void | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 182 | t_bootstrap(void *boot_raw) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 183 | { | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 184 | 	struct bootstate *boot = (struct bootstate *) boot_raw; | 
| Guido van Rossum | 75aa0d6 | 1997-07-18 23:57:50 +0000 | [diff] [blame] | 185 | 	PyThreadState *tstate; | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 186 | 	PyObject *res; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 187 |  | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 188 | 	tstate = PyThreadState_New(boot->interp); | 
| Guido van Rossum | 75aa0d6 | 1997-07-18 23:57:50 +0000 | [diff] [blame] | 189 | 	PyEval_AcquireThread(tstate); | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 190 | 	res = PyEval_CallObjectWithKeywords( | 
 | 191 | 		boot->func, boot->args, boot->keyw); | 
 | 192 | 	Py_DECREF(boot->func); | 
 | 193 | 	Py_DECREF(boot->args); | 
 | 194 | 	Py_XDECREF(boot->keyw); | 
 | 195 | 	PyMem_DEL(boot_raw); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 196 | 	if (res == NULL) { | 
| Fred Drake | bebc97f | 1998-05-28 04:35:12 +0000 | [diff] [blame] | 197 | 		if (PyErr_ExceptionMatches(PyExc_SystemExit)) | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 198 | 			PyErr_Clear(); | 
| Guido van Rossum | 385e7c6 | 1995-03-17 10:42:27 +0000 | [diff] [blame] | 199 | 		else { | 
| Fred Drake | 9c801ab | 2000-10-20 20:02:37 +0000 | [diff] [blame] | 200 | 			PySys_WriteStderr("Unhandled exception in thread:\n"); | 
| Guido van Rossum | 40769dd | 1998-02-06 22:32:08 +0000 | [diff] [blame] | 201 | 			PyErr_PrintEx(0); | 
| Guido van Rossum | 385e7c6 | 1995-03-17 10:42:27 +0000 | [diff] [blame] | 202 | 		} | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 203 | 	} | 
| Guido van Rossum | 3bbc62e | 1995-01-02 19:30:30 +0000 | [diff] [blame] | 204 | 	else | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 205 | 		Py_DECREF(res); | 
| Guido van Rossum | b02158e | 1997-08-02 03:13:11 +0000 | [diff] [blame] | 206 | 	PyThreadState_Clear(tstate); | 
| Guido van Rossum | 2528b19 | 2001-01-23 01:47:18 +0000 | [diff] [blame] | 207 | 	PyThreadState_DeleteCurrent(); | 
| Guido van Rossum | bcc2074 | 1998-08-04 22:53:56 +0000 | [diff] [blame] | 208 | 	PyThread_exit_thread(); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 209 | } | 
 | 210 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 211 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 212 | thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 213 | { | 
| Guido van Rossum | 38d45b7 | 2000-09-01 20:47:58 +0000 | [diff] [blame] | 214 | 	PyObject *func, *args, *keyw = NULL; | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 215 | 	struct bootstate *boot; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 216 |  | 
| Guido van Rossum | 43713e5 | 2000-02-29 13:59:29 +0000 | [diff] [blame] | 217 | 	if (!PyArg_ParseTuple(fargs, "OO|O:start_new_thread", &func, &args, &keyw)) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 218 | 		return NULL; | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 219 | 	if (!PyCallable_Check(func)) { | 
 | 220 | 		PyErr_SetString(PyExc_TypeError, | 
 | 221 | 				"first arg must be callable"); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 222 | 		return NULL; | 
 | 223 | 	} | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 224 | 	if (!PyTuple_Check(args)) { | 
 | 225 | 		PyErr_SetString(PyExc_TypeError, | 
| Guido van Rossum | 38d45b7 | 2000-09-01 20:47:58 +0000 | [diff] [blame] | 226 | 				"2nd arg must be a tuple"); | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 227 | 		return NULL; | 
 | 228 | 	} | 
 | 229 | 	if (keyw != NULL && !PyDict_Check(keyw)) { | 
 | 230 | 		PyErr_SetString(PyExc_TypeError, | 
 | 231 | 				"optional 3rd arg must be a dictionary"); | 
 | 232 | 		return NULL; | 
 | 233 | 	} | 
 | 234 | 	boot = PyMem_NEW(struct bootstate, 1); | 
 | 235 | 	if (boot == NULL) | 
 | 236 | 		return PyErr_NoMemory(); | 
| Guido van Rossum | b02158e | 1997-08-02 03:13:11 +0000 | [diff] [blame] | 237 | 	boot->interp = PyThreadState_Get()->interp; | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 238 | 	boot->func = func; | 
 | 239 | 	boot->args = args; | 
 | 240 | 	boot->keyw = keyw; | 
 | 241 | 	Py_INCREF(func); | 
 | 242 | 	Py_INCREF(args); | 
 | 243 | 	Py_XINCREF(keyw); | 
 | 244 | 	PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 245 | 	if (!PyThread_start_new_thread(t_bootstrap, (void*) boot)) { | 
| Guido van Rossum | a027efa | 1997-05-05 20:56:21 +0000 | [diff] [blame] | 246 | 		PyErr_SetString(ThreadError, "can't start new thread\n"); | 
 | 247 | 		Py_DECREF(func); | 
 | 248 | 		Py_DECREF(args); | 
 | 249 | 		Py_XDECREF(keyw); | 
 | 250 | 		PyMem_DEL(boot); | 
 | 251 | 		return NULL; | 
 | 252 | 	} | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 253 | 	Py_INCREF(Py_None); | 
 | 254 | 	return Py_None; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 255 | } | 
 | 256 |  | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 257 | static char start_new_doc[] = | 
 | 258 | "start_new_thread(functon, args[, kwargs])\n\ | 
 | 259 | (start_new() is an obsolete synonym)\n\ | 
 | 260 | \n\ | 
 | 261 | Start a new thread.  The thread will call the function with positional\n\ | 
 | 262 | arguments from the tuple args and keyword arguments taken from the optional\n\ | 
 | 263 | dictionary kwargs.  The thread exits when the function returns; the return\n\ | 
 | 264 | value is ignored.  The thread will also exit when the function raises an\n\ | 
 | 265 | unhandled exception; a stack trace will be printed unless the exception is\n\ | 
 | 266 | SystemExit."; | 
 | 267 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 268 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 269 | thread_PyThread_exit_thread(PyObject *self, PyObject *args) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 270 | { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 271 | 	if (!PyArg_NoArgs(args)) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 272 | 		return NULL; | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 273 | 	PyErr_SetNone(PyExc_SystemExit); | 
| Guido van Rossum | 385e7c6 | 1995-03-17 10:42:27 +0000 | [diff] [blame] | 274 | 	return NULL; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 275 | } | 
 | 276 |  | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 277 | static char exit_doc[] = | 
 | 278 | "exit()\n\ | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 279 | (PyThread_exit_thread() is an obsolete synonym)\n\ | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 280 | \n\ | 
 | 281 | This is synonymous to ``raise SystemExit''.  It will cause the current\n\ | 
 | 282 | thread to exit silently unless the exception is caught."; | 
 | 283 |  | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 284 | #ifndef NO_EXIT_PROG | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 285 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 286 | thread_PyThread_exit_prog(PyObject *self, PyObject *args) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 287 | { | 
 | 288 | 	int sts; | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 289 | 	if (!PyArg_Parse(args, "i", &sts)) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 290 | 		return NULL; | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 291 | 	Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */ | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 292 | 	for (;;) { } /* Should not be reached */ | 
 | 293 | } | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 294 | #endif | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 295 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 296 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 297 | thread_PyThread_allocate_lock(PyObject *self, PyObject *args) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 298 | { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 299 | 	if (!PyArg_NoArgs(args)) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 300 | 		return NULL; | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 301 | 	return (PyObject *) newlockobject(); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 302 | } | 
 | 303 |  | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 304 | static char allocate_doc[] = | 
 | 305 | "allocate_lock() -> lock object\n\ | 
 | 306 | (allocate() is an obsolete synonym)\n\ | 
 | 307 | \n\ | 
 | 308 | Create a new lock object.  See LockType.__doc__ for information about locks."; | 
 | 309 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 310 | static PyObject * | 
| Peter Schneider-Kamp | 3707efe | 2000-07-10 10:03:58 +0000 | [diff] [blame] | 311 | thread_get_ident(PyObject *self, PyObject *args) | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 312 | { | 
 | 313 | 	long ident; | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 314 | 	if (!PyArg_NoArgs(args)) | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 315 | 		return NULL; | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 316 | 	ident = PyThread_get_thread_ident(); | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 317 | 	if (ident == -1) { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 318 | 		PyErr_SetString(ThreadError, "no current thread ident"); | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 319 | 		return NULL; | 
 | 320 | 	} | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 321 | 	return PyInt_FromLong(ident); | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 322 | } | 
 | 323 |  | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 324 | static char get_ident_doc[] = | 
 | 325 | "get_ident() -> integer\n\ | 
 | 326 | \n\ | 
 | 327 | Return a non-zero integer that uniquely identifies the current thread\n\ | 
 | 328 | amongst other threads that exist simultaneously.\n\ | 
 | 329 | This may be used to identify per-thread resources.\n\ | 
 | 330 | Even though on some platforms threads identities may appear to be\n\ | 
 | 331 | allocated consecutive numbers starting at 1, this behavior should not\n\ | 
 | 332 | be relied upon, and the number should be seen purely as a magic cookie.\n\ | 
 | 333 | A thread's identity may be reused for another thread after it exits."; | 
 | 334 |  | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 335 | static PyMethodDef thread_methods[] = { | 
| Andrew M. Kuchling | e365fb8 | 2000-08-03 02:06:16 +0000 | [diff] [blame] | 336 | 	{"start_new_thread",	(PyCFunction)thread_PyThread_start_new_thread, | 
 | 337 | 	                        METH_VARARGS, | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 338 | 				start_new_doc}, | 
| Andrew M. Kuchling | e365fb8 | 2000-08-03 02:06:16 +0000 | [diff] [blame] | 339 | 	{"start_new",		(PyCFunction)thread_PyThread_start_new_thread,  | 
 | 340 | 	                        METH_VARARGS, | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 341 | 				start_new_doc}, | 
| Andrew M. Kuchling | a1abb72 | 2000-08-03 02:34:44 +0000 | [diff] [blame] | 342 | 	{"allocate_lock",	(PyCFunction)thread_PyThread_allocate_lock,  | 
 | 343 | 	 METH_OLDARGS, allocate_doc}, | 
 | 344 | 	{"allocate",		(PyCFunction)thread_PyThread_allocate_lock,  | 
 | 345 | 	 METH_OLDARGS, allocate_doc}, | 
 | 346 | 	{"exit_thread",		(PyCFunction)thread_PyThread_exit_thread,  | 
 | 347 | 	 METH_OLDARGS, exit_doc}, | 
 | 348 | 	{"exit",		(PyCFunction)thread_PyThread_exit_thread,  | 
 | 349 | 	 METH_OLDARGS, exit_doc}, | 
 | 350 | 	{"get_ident",		(PyCFunction)thread_get_ident,  | 
 | 351 | 	 METH_OLDARGS, get_ident_doc}, | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 352 | #ifndef NO_EXIT_PROG | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 353 | 	{"exit_prog",		(PyCFunction)thread_PyThread_exit_prog}, | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 354 | #endif | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 355 | 	{NULL,			NULL}		/* sentinel */ | 
 | 356 | }; | 
 | 357 |  | 
 | 358 |  | 
 | 359 | /* Initialization function */ | 
 | 360 |  | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 361 | static char thread_doc[] = | 
 | 362 | "This module provides primitive operations to write multi-threaded programs.\n\ | 
 | 363 | The 'threading' module provides a more convenient interface."; | 
 | 364 |  | 
 | 365 | static char lock_doc[] = | 
 | 366 | "A lock object is a synchronization primitive.  To create a lock,\n\ | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 367 | call the PyThread_allocate_lock() function.  Methods are:\n\ | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 368 | \n\ | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 369 | acquire() -- lock the lock, possibly blocking until it can be obtained\n\ | 
 | 370 | release() -- unlock of the lock\n\ | 
 | 371 | locked() -- test whether the lock is currently locked\n\ | 
 | 372 | \n\ | 
 | 373 | A lock is not owned by the thread that locked it; another thread may\n\ | 
 | 374 | unlock it.  A thread attempting to lock a lock that it has already locked\n\ | 
 | 375 | will block until another thread unlocks it.  Deadlocks may ensue."; | 
 | 376 |  | 
| Guido van Rossum | 3886bb6 | 1998-12-04 18:50:17 +0000 | [diff] [blame] | 377 | DL_EXPORT(void) | 
| Thomas Wouters | f3f33dc | 2000-07-21 06:00:07 +0000 | [diff] [blame] | 378 | initthread(void) | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 379 | { | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 380 | 	PyObject *m, *d; | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 381 |  | 
 | 382 | 	/* Create the module and add the functions */ | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 383 | 	m = Py_InitModule3("thread", thread_methods, thread_doc); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 384 |  | 
 | 385 | 	/* Add a symbolic constant */ | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 386 | 	d = PyModule_GetDict(m); | 
| Guido van Rossum | 0cb96de | 1997-10-01 04:29:29 +0000 | [diff] [blame] | 387 | 	ThreadError = PyErr_NewException("thread.error", NULL, NULL); | 
| Barry Warsaw | d0c1042 | 1996-12-17 00:05:22 +0000 | [diff] [blame] | 388 | 	PyDict_SetItemString(d, "error", ThreadError); | 
| Guido van Rossum | 75e9fc3 | 1998-06-27 18:21:06 +0000 | [diff] [blame] | 389 | 	Locktype.tp_doc = lock_doc; | 
 | 390 | 	Py_INCREF(&Locktype); | 
 | 391 | 	PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 392 |  | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 393 | 	/* Initialize the C thread library */ | 
| Guido van Rossum | 65d5b57 | 1998-12-21 19:32:43 +0000 | [diff] [blame] | 394 | 	PyThread_init_thread(); | 
| Guido van Rossum | 1984f1e | 1992-08-04 12:41:02 +0000 | [diff] [blame] | 395 | } |