comparison Modules/_threadmodule.c @ 61467:f197407bdba2 3.1

Recorded merge of revisions 81032 via svnmerge from svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r81032 | antoine.pitrou | 2010-05-09 17:52:27 +0200 (dim., 09 mai 2010) | 9 lines Recorded merge of revisions 81029 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines Untabify C files. Will watch buildbots. ........ ................
author Antoine Pitrou <solipsis@pitrou.net>
date Sun, 09 May 2010 16:14:21 +0000
parents d7a62c16505b
children 109bde5e41b9
comparison
equal deleted inserted replaced
61459:f8c19c5f5dd2 61467:f197407bdba2
16 16
17 17
18 /* Lock objects */ 18 /* Lock objects */
19 19
20 typedef struct { 20 typedef struct {
21 PyObject_HEAD 21 PyObject_HEAD
22 PyThread_type_lock lock_lock; 22 PyThread_type_lock lock_lock;
23 } lockobject; 23 } lockobject;
24 24
25 static void 25 static void
26 lock_dealloc(lockobject *self) 26 lock_dealloc(lockobject *self)
27 { 27 {
28 if (self->lock_lock != NULL) { 28 if (self->lock_lock != NULL) {
29 /* Unlock the lock so it's safe to free it */ 29 /* Unlock the lock so it's safe to free it */
30 PyThread_acquire_lock(self->lock_lock, 0); 30 PyThread_acquire_lock(self->lock_lock, 0);
31 PyThread_release_lock(self->lock_lock); 31 PyThread_release_lock(self->lock_lock);
32 32
33 PyThread_free_lock(self->lock_lock); 33 PyThread_free_lock(self->lock_lock);
34 } 34 }
35 PyObject_Del(self); 35 PyObject_Del(self);
36 } 36 }
37 37
38 static PyObject * 38 static PyObject *
39 lock_PyThread_acquire_lock(lockobject *self, PyObject *args) 39 lock_PyThread_acquire_lock(lockobject *self, PyObject *args)
40 { 40 {
41 int i = 1; 41 int i = 1;
42 42
43 if (!PyArg_ParseTuple(args, "|i:acquire", &i)) 43 if (!PyArg_ParseTuple(args, "|i:acquire", &i))
44 return NULL; 44 return NULL;
45 45
46 Py_BEGIN_ALLOW_THREADS 46 Py_BEGIN_ALLOW_THREADS
47 i = PyThread_acquire_lock(self->lock_lock, i); 47 i = PyThread_acquire_lock(self->lock_lock, i);
48 Py_END_ALLOW_THREADS 48 Py_END_ALLOW_THREADS
49 49
50 return PyBool_FromLong((long)i); 50 return PyBool_FromLong((long)i);
51 } 51 }
52 52
53 PyDoc_STRVAR(acquire_doc, 53 PyDoc_STRVAR(acquire_doc,
54 "acquire([wait]) -> None or bool\n\ 54 "acquire([wait]) -> None or bool\n\
55 (acquire_lock() is an obsolete synonym)\n\ 55 (acquire_lock() is an obsolete synonym)\n\
62 The blocking operation is not interruptible."); 62 The blocking operation is not interruptible.");
63 63
64 static PyObject * 64 static PyObject *
65 lock_PyThread_release_lock(lockobject *self) 65 lock_PyThread_release_lock(lockobject *self)
66 { 66 {
67 /* Sanity check: the lock must be locked */ 67 /* Sanity check: the lock must be locked */
68 if (PyThread_acquire_lock(self->lock_lock, 0)) { 68 if (PyThread_acquire_lock(self->lock_lock, 0)) {
69 PyThread_release_lock(self->lock_lock); 69 PyThread_release_lock(self->lock_lock);
70 PyErr_SetString(ThreadError, "release unlocked lock"); 70 PyErr_SetString(ThreadError, "release unlocked lock");
71 return NULL; 71 return NULL;
72 } 72 }
73 73
74 PyThread_release_lock(self->lock_lock); 74 PyThread_release_lock(self->lock_lock);
75 Py_INCREF(Py_None); 75 Py_INCREF(Py_None);
76 return Py_None; 76 return Py_None;
77 } 77 }
78 78
79 PyDoc_STRVAR(release_doc, 79 PyDoc_STRVAR(release_doc,
80 "release()\n\ 80 "release()\n\
81 (release_lock() is an obsolete synonym)\n\ 81 (release_lock() is an obsolete synonym)\n\
85 but it needn't be locked by the same thread that unlocks it."); 85 but it needn't be locked by the same thread that unlocks it.");
86 86
87 static PyObject * 87 static PyObject *
88 lock_locked_lock(lockobject *self) 88 lock_locked_lock(lockobject *self)
89 { 89 {
90 if (PyThread_acquire_lock(self->lock_lock, 0)) { 90 if (PyThread_acquire_lock(self->lock_lock, 0)) {
91 PyThread_release_lock(self->lock_lock); 91 PyThread_release_lock(self->lock_lock);
92 return PyBool_FromLong(0L); 92 return PyBool_FromLong(0L);
93 } 93 }
94 return PyBool_FromLong(1L); 94 return PyBool_FromLong(1L);
95 } 95 }
96 96
97 PyDoc_STRVAR(locked_doc, 97 PyDoc_STRVAR(locked_doc,
98 "locked() -> bool\n\ 98 "locked() -> bool\n\
99 (locked_lock() is an obsolete synonym)\n\ 99 (locked_lock() is an obsolete synonym)\n\
100 \n\ 100 \n\
101 Return whether the lock is in the locked state."); 101 Return whether the lock is in the locked state.");
102 102
103 static PyMethodDef lock_methods[] = { 103 static PyMethodDef lock_methods[] = {
104 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, 104 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
105 METH_VARARGS, acquire_doc}, 105 METH_VARARGS, acquire_doc},
106 {"acquire", (PyCFunction)lock_PyThread_acquire_lock, 106 {"acquire", (PyCFunction)lock_PyThread_acquire_lock,
107 METH_VARARGS, acquire_doc}, 107 METH_VARARGS, acquire_doc},
108 {"release_lock", (PyCFunction)lock_PyThread_release_lock, 108 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
109 METH_NOARGS, release_doc}, 109 METH_NOARGS, release_doc},
110 {"release", (PyCFunction)lock_PyThread_release_lock, 110 {"release", (PyCFunction)lock_PyThread_release_lock,
111 METH_NOARGS, release_doc}, 111 METH_NOARGS, release_doc},
112 {"locked_lock", (PyCFunction)lock_locked_lock, 112 {"locked_lock", (PyCFunction)lock_locked_lock,
113 METH_NOARGS, locked_doc}, 113 METH_NOARGS, locked_doc},
114 {"locked", (PyCFunction)lock_locked_lock, 114 {"locked", (PyCFunction)lock_locked_lock,
115 METH_NOARGS, locked_doc}, 115 METH_NOARGS, locked_doc},
116 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock, 116 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock,
117 METH_VARARGS, acquire_doc}, 117 METH_VARARGS, acquire_doc},
118 {"__exit__", (PyCFunction)lock_PyThread_release_lock, 118 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
119 METH_VARARGS, release_doc}, 119 METH_VARARGS, release_doc},
120 {NULL, NULL} /* sentinel */ 120 {NULL, NULL} /* sentinel */
121 }; 121 };
122 122
123 static PyTypeObject Locktype = { 123 static PyTypeObject Locktype = {
124 PyVarObject_HEAD_INIT(&PyType_Type, 0) 124 PyVarObject_HEAD_INIT(&PyType_Type, 0)
125 "_thread.lock", /*tp_name*/ 125 "_thread.lock", /*tp_name*/
126 sizeof(lockobject), /*tp_size*/ 126 sizeof(lockobject), /*tp_size*/
127 0, /*tp_itemsize*/ 127 0, /*tp_itemsize*/
128 /* methods */ 128 /* methods */
129 (destructor)lock_dealloc, /*tp_dealloc*/ 129 (destructor)lock_dealloc, /*tp_dealloc*/
130 0, /*tp_print*/ 130 0, /*tp_print*/
131 0, /*tp_getattr*/ 131 0, /*tp_getattr*/
132 0, /*tp_setattr*/ 132 0, /*tp_setattr*/
133 0, /*tp_reserved*/ 133 0, /*tp_reserved*/
134 0, /*tp_repr*/ 134 0, /*tp_repr*/
135 0, /*tp_as_number*/ 135 0, /*tp_as_number*/
136 0, /*tp_as_sequence*/ 136 0, /*tp_as_sequence*/
137 0, /*tp_as_mapping*/ 137 0, /*tp_as_mapping*/
138 0, /*tp_hash*/ 138 0, /*tp_hash*/
139 0, /*tp_call*/ 139 0, /*tp_call*/
140 0, /*tp_str*/ 140 0, /*tp_str*/
141 0, /*tp_getattro*/ 141 0, /*tp_getattro*/
142 0, /*tp_setattro*/ 142 0, /*tp_setattro*/
143 0, /*tp_as_buffer*/ 143 0, /*tp_as_buffer*/
144 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 144 Py_TPFLAGS_DEFAULT, /*tp_flags*/
145 0, /*tp_doc*/ 145 0, /*tp_doc*/
146 0, /*tp_traverse*/ 146 0, /*tp_traverse*/
147 0, /*tp_clear*/ 147 0, /*tp_clear*/
148 0, /*tp_richcompare*/ 148 0, /*tp_richcompare*/
149 0, /*tp_weaklistoffset*/ 149 0, /*tp_weaklistoffset*/
150 0, /*tp_iter*/ 150 0, /*tp_iter*/
151 0, /*tp_iternext*/ 151 0, /*tp_iternext*/
152 lock_methods, /*tp_methods*/ 152 lock_methods, /*tp_methods*/
153 }; 153 };
154 154
155 static lockobject * 155 static lockobject *
156 newlockobject(void) 156 newlockobject(void)
157 { 157 {
158 lockobject *self; 158 lockobject *self;
159 self = PyObject_New(lockobject, &Locktype); 159 self = PyObject_New(lockobject, &Locktype);
160 if (self == NULL) 160 if (self == NULL)
161 return NULL; 161 return NULL;
162 self->lock_lock = PyThread_allocate_lock(); 162 self->lock_lock = PyThread_allocate_lock();
163 if (self->lock_lock == NULL) { 163 if (self->lock_lock == NULL) {
164 Py_DECREF(self); 164 Py_DECREF(self);
165 PyErr_SetString(ThreadError, "can't allocate lock"); 165 PyErr_SetString(ThreadError, "can't allocate lock");
166 return NULL; 166 return NULL;
167 } 167 }
168 return self; 168 return self;
169 } 169 }
170 170
171 /* Thread-local objects */ 171 /* Thread-local objects */
172 172
173 #include "structmember.h" 173 #include "structmember.h"
174 174
175 typedef struct { 175 typedef struct {
176 PyObject_HEAD 176 PyObject_HEAD
177 PyObject *key; 177 PyObject *key;
178 PyObject *args; 178 PyObject *args;
179 PyObject *kw; 179 PyObject *kw;
180 PyObject *dict; 180 PyObject *dict;
181 } localobject; 181 } localobject;
182 182
183 static PyObject * 183 static PyObject *
184 local_new(PyTypeObject *type, PyObject *args, PyObject *kw) 184 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
185 { 185 {
186 localobject *self; 186 localobject *self;
187 PyObject *tdict; 187 PyObject *tdict;
188 188
189 if (type->tp_init == PyBaseObject_Type.tp_init 189 if (type->tp_init == PyBaseObject_Type.tp_init
190 && ((args && PyObject_IsTrue(args)) 190 && ((args && PyObject_IsTrue(args))
191 || (kw && PyObject_IsTrue(kw)))) { 191 || (kw && PyObject_IsTrue(kw)))) {
192 PyErr_SetString(PyExc_TypeError, 192 PyErr_SetString(PyExc_TypeError,
193 "Initialization arguments are not supported"); 193 "Initialization arguments are not supported");
194 return NULL; 194 return NULL;
195 } 195 }
196 196
197 self = (localobject *)type->tp_alloc(type, 0); 197 self = (localobject *)type->tp_alloc(type, 0);
198 if (self == NULL) 198 if (self == NULL)
199 return NULL; 199 return NULL;
200 200
201 Py_XINCREF(args); 201 Py_XINCREF(args);
202 self->args = args; 202 self->args = args;
203 Py_XINCREF(kw); 203 Py_XINCREF(kw);
204 self->kw = kw; 204 self->kw = kw;
205 self->dict = NULL; /* making sure */ 205 self->dict = NULL; /* making sure */
206 self->key = PyUnicode_FromFormat("thread.local.%p", self); 206 self->key = PyUnicode_FromFormat("thread.local.%p", self);
207 if (self->key == NULL) 207 if (self->key == NULL)
208 goto err; 208 goto err;
209 209
210 self->dict = PyDict_New(); 210 self->dict = PyDict_New();
211 if (self->dict == NULL) 211 if (self->dict == NULL)
212 goto err; 212 goto err;
213 213
214 tdict = PyThreadState_GetDict(); 214 tdict = PyThreadState_GetDict();
215 if (tdict == NULL) { 215 if (tdict == NULL) {
216 PyErr_SetString(PyExc_SystemError, 216 PyErr_SetString(PyExc_SystemError,
217 "Couldn't get thread-state dictionary"); 217 "Couldn't get thread-state dictionary");
218 goto err; 218 goto err;
219 } 219 }
220 220
221 if (PyDict_SetItem(tdict, self->key, self->dict) < 0) 221 if (PyDict_SetItem(tdict, self->key, self->dict) < 0)
222 goto err; 222 goto err;
223 223
224 return (PyObject *)self; 224 return (PyObject *)self;
225 225
226 err: 226 err:
227 Py_DECREF(self); 227 Py_DECREF(self);
228 return NULL; 228 return NULL;
229 } 229 }
230 230
231 static int 231 static int
232 local_traverse(localobject *self, visitproc visit, void *arg) 232 local_traverse(localobject *self, visitproc visit, void *arg)
233 { 233 {
234 Py_VISIT(self->args); 234 Py_VISIT(self->args);
235 Py_VISIT(self->kw); 235 Py_VISIT(self->kw);
236 Py_VISIT(self->dict); 236 Py_VISIT(self->dict);
237 return 0; 237 return 0;
238 } 238 }
239 239
240 static int 240 static int
241 local_clear(localobject *self) 241 local_clear(localobject *self)
242 { 242 {
243 Py_CLEAR(self->args); 243 Py_CLEAR(self->args);
244 Py_CLEAR(self->kw); 244 Py_CLEAR(self->kw);
245 Py_CLEAR(self->dict); 245 Py_CLEAR(self->dict);
246 return 0; 246 return 0;
247 } 247 }
248 248
249 static void 249 static void
250 local_dealloc(localobject *self) 250 local_dealloc(localobject *self)
251 { 251 {
252 PyThreadState *tstate; 252 PyThreadState *tstate;
253 if (self->key 253 if (self->key
254 && (tstate = PyThreadState_Get()) 254 && (tstate = PyThreadState_Get())
255 && tstate->interp) { 255 && tstate->interp) {
256 for(tstate = PyInterpreterState_ThreadHead(tstate->interp); 256 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
257 tstate; 257 tstate;
258 tstate = PyThreadState_Next(tstate)) 258 tstate = PyThreadState_Next(tstate))
259 if (tstate->dict && 259 if (tstate->dict &&
260 PyDict_GetItem(tstate->dict, self->key)) 260 PyDict_GetItem(tstate->dict, self->key))
261 PyDict_DelItem(tstate->dict, self->key); 261 PyDict_DelItem(tstate->dict, self->key);
262 } 262 }
263 263
264 Py_XDECREF(self->key); 264 Py_XDECREF(self->key);
265 local_clear(self); 265 local_clear(self);
266 Py_TYPE(self)->tp_free((PyObject*)self); 266 Py_TYPE(self)->tp_free((PyObject*)self);
267 } 267 }
268 268
269 static PyObject * 269 static PyObject *
270 _ldict(localobject *self) 270 _ldict(localobject *self)
271 { 271 {
272 PyObject *tdict, *ldict; 272 PyObject *tdict, *ldict;
273 273
274 tdict = PyThreadState_GetDict(); 274 tdict = PyThreadState_GetDict();
275 if (tdict == NULL) { 275 if (tdict == NULL) {
276 PyErr_SetString(PyExc_SystemError, 276 PyErr_SetString(PyExc_SystemError,
277 "Couldn't get thread-state dictionary"); 277 "Couldn't get thread-state dictionary");
278 return NULL; 278 return NULL;
279 } 279 }
280 280
281 ldict = PyDict_GetItem(tdict, self->key); 281 ldict = PyDict_GetItem(tdict, self->key);
282 if (ldict == NULL) { 282 if (ldict == NULL) {
283 ldict = PyDict_New(); /* we own ldict */ 283 ldict = PyDict_New(); /* we own ldict */
284 284
285 if (ldict == NULL) 285 if (ldict == NULL)
286 return NULL; 286 return NULL;
287 else { 287 else {
288 int i = PyDict_SetItem(tdict, self->key, ldict); 288 int i = PyDict_SetItem(tdict, self->key, ldict);
289 Py_DECREF(ldict); /* now ldict is borrowed */ 289 Py_DECREF(ldict); /* now ldict is borrowed */
290 if (i < 0) 290 if (i < 0)
291 return NULL; 291 return NULL;
292 } 292 }
293 293
294 Py_CLEAR(self->dict); 294 Py_CLEAR(self->dict);
295 Py_INCREF(ldict); 295 Py_INCREF(ldict);
296 self->dict = ldict; /* still borrowed */ 296 self->dict = ldict; /* still borrowed */
297 297
298 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && 298 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
299 Py_TYPE(self)->tp_init((PyObject*)self, 299 Py_TYPE(self)->tp_init((PyObject*)self,
300 self->args, self->kw) < 0) { 300 self->args, self->kw) < 0) {
301 /* we need to get rid of ldict from thread so 301 /* we need to get rid of ldict from thread so
302 we create a new one the next time we do an attr 302 we create a new one the next time we do an attr
303 acces */ 303 acces */
304 PyDict_DelItem(tdict, self->key); 304 PyDict_DelItem(tdict, self->key);
305 return NULL; 305 return NULL;
306 } 306 }
307 307
308 } 308 }
309 309
310 /* The call to tp_init above may have caused another thread to run. 310 /* The call to tp_init above may have caused another thread to run.
311 Install our ldict again. */ 311 Install our ldict again. */
312 if (self->dict != ldict) { 312 if (self->dict != ldict) {
313 Py_CLEAR(self->dict); 313 Py_CLEAR(self->dict);
314 Py_INCREF(ldict); 314 Py_INCREF(ldict);
315 self->dict = ldict; 315 self->dict = ldict;
316 } 316 }
317 317
318 return ldict; 318 return ldict;
319 } 319 }
320 320
321 static int 321 static int
322 local_setattro(localobject *self, PyObject *name, PyObject *v) 322 local_setattro(localobject *self, PyObject *name, PyObject *v)
323 { 323 {
324 PyObject *ldict; 324 PyObject *ldict;
325 325
326 ldict = _ldict(self); 326 ldict = _ldict(self);
327 if (ldict == NULL) 327 if (ldict == NULL)
328 return -1; 328 return -1;
329 329
330 return PyObject_GenericSetAttr((PyObject *)self, name, v); 330 return PyObject_GenericSetAttr((PyObject *)self, name, v);
331 } 331 }
332 332
333 static PyObject * 333 static PyObject *
334 local_getdict(localobject *self, void *closure) 334 local_getdict(localobject *self, void *closure)
335 { 335 {
336 if (self->dict == NULL) { 336 if (self->dict == NULL) {
337 PyErr_SetString(PyExc_AttributeError, "__dict__"); 337 PyErr_SetString(PyExc_AttributeError, "__dict__");
338 return NULL; 338 return NULL;
339 } 339 }
340 340
341 Py_INCREF(self->dict); 341 Py_INCREF(self->dict);
342 return self->dict; 342 return self->dict;
343 } 343 }
344 344
345 static PyGetSetDef local_getset[] = { 345 static PyGetSetDef local_getset[] = {
346 {"__dict__", (getter)local_getdict, (setter)NULL, 346 {"__dict__", (getter)local_getdict, (setter)NULL,
347 "Local-data dictionary", NULL}, 347 "Local-data dictionary", NULL},
348 {NULL} /* Sentinel */ 348 {NULL} /* Sentinel */
349 }; 349 };
350 350
351 static PyObject *local_getattro(localobject *, PyObject *); 351 static PyObject *local_getattro(localobject *, PyObject *);
352 352
353 static PyTypeObject localtype = { 353 static PyTypeObject localtype = {
354 PyVarObject_HEAD_INIT(NULL, 0) 354 PyVarObject_HEAD_INIT(NULL, 0)
355 /* tp_name */ "_thread._local", 355 /* tp_name */ "_thread._local",
356 /* tp_basicsize */ sizeof(localobject), 356 /* tp_basicsize */ sizeof(localobject),
357 /* tp_itemsize */ 0, 357 /* tp_itemsize */ 0,
358 /* tp_dealloc */ (destructor)local_dealloc, 358 /* tp_dealloc */ (destructor)local_dealloc,
359 /* tp_print */ 0, 359 /* tp_print */ 0,
360 /* tp_getattr */ 0, 360 /* tp_getattr */ 0,
361 /* tp_setattr */ 0, 361 /* tp_setattr */ 0,
362 /* tp_reserved */ 0, 362 /* tp_reserved */ 0,
363 /* tp_repr */ 0, 363 /* tp_repr */ 0,
364 /* tp_as_number */ 0, 364 /* tp_as_number */ 0,
365 /* tp_as_sequence */ 0, 365 /* tp_as_sequence */ 0,
366 /* tp_as_mapping */ 0, 366 /* tp_as_mapping */ 0,
367 /* tp_hash */ 0, 367 /* tp_hash */ 0,
368 /* tp_call */ 0, 368 /* tp_call */ 0,
369 /* tp_str */ 0, 369 /* tp_str */ 0,
370 /* tp_getattro */ (getattrofunc)local_getattro, 370 /* tp_getattro */ (getattrofunc)local_getattro,
371 /* tp_setattro */ (setattrofunc)local_setattro, 371 /* tp_setattro */ (setattrofunc)local_setattro,
372 /* tp_as_buffer */ 0, 372 /* tp_as_buffer */ 0,
373 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 373 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
374 /* tp_doc */ "Thread-local data", 374 /* tp_doc */ "Thread-local data",
375 /* tp_traverse */ (traverseproc)local_traverse, 375 /* tp_traverse */ (traverseproc)local_traverse,
376 /* tp_clear */ (inquiry)local_clear, 376 /* tp_clear */ (inquiry)local_clear,
377 /* tp_richcompare */ 0, 377 /* tp_richcompare */ 0,
378 /* tp_weaklistoffset */ 0, 378 /* tp_weaklistoffset */ 0,
379 /* tp_iter */ 0, 379 /* tp_iter */ 0,
380 /* tp_iternext */ 0, 380 /* tp_iternext */ 0,
381 /* tp_methods */ 0, 381 /* tp_methods */ 0,
382 /* tp_members */ 0, 382 /* tp_members */ 0,
383 /* tp_getset */ local_getset, 383 /* tp_getset */ local_getset,
384 /* tp_base */ 0, 384 /* tp_base */ 0,
385 /* tp_dict */ 0, /* internal use */ 385 /* tp_dict */ 0, /* internal use */
386 /* tp_descr_get */ 0, 386 /* tp_descr_get */ 0,
387 /* tp_descr_set */ 0, 387 /* tp_descr_set */ 0,
388 /* tp_dictoffset */ offsetof(localobject, dict), 388 /* tp_dictoffset */ offsetof(localobject, dict),
389 /* tp_init */ 0, 389 /* tp_init */ 0,
390 /* tp_alloc */ 0, 390 /* tp_alloc */ 0,
391 /* tp_new */ local_new, 391 /* tp_new */ local_new,
392 /* tp_free */ 0, /* Low-level free-mem routine */ 392 /* tp_free */ 0, /* Low-level free-mem routine */
393 /* tp_is_gc */ 0, /* For PyObject_IS_GC */ 393 /* tp_is_gc */ 0, /* For PyObject_IS_GC */
394 }; 394 };
395 395
396 static PyObject * 396 static PyObject *
397 local_getattro(localobject *self, PyObject *name) 397 local_getattro(localobject *self, PyObject *name)
398 { 398 {
399 PyObject *ldict, *value; 399 PyObject *ldict, *value;
400 400
401 ldict = _ldict(self); 401 ldict = _ldict(self);
402 if (ldict == NULL) 402 if (ldict == NULL)
403 return NULL; 403 return NULL;
404 404
405 if (Py_TYPE(self) != &localtype) 405 if (Py_TYPE(self) != &localtype)
406 /* use generic lookup for subtypes */ 406 /* use generic lookup for subtypes */
407 return PyObject_GenericGetAttr((PyObject *)self, name); 407 return PyObject_GenericGetAttr((PyObject *)self, name);
408 408
409 /* Optimization: just look in dict ourselves */ 409 /* Optimization: just look in dict ourselves */
410 value = PyDict_GetItem(ldict, name); 410 value = PyDict_GetItem(ldict, name);
411 if (value == NULL) 411 if (value == NULL)
412 /* Fall back on generic to get __class__ and __dict__ */ 412 /* Fall back on generic to get __class__ and __dict__ */
413 return PyObject_GenericGetAttr((PyObject *)self, name); 413 return PyObject_GenericGetAttr((PyObject *)self, name);
414 414
415 Py_INCREF(value); 415 Py_INCREF(value);
416 return value; 416 return value;
417 } 417 }
418 418
419 /* Module functions */ 419 /* Module functions */
420 420
421 struct bootstate { 421 struct bootstate {
422 PyInterpreterState *interp; 422 PyInterpreterState *interp;
423 PyObject *func; 423 PyObject *func;
424 PyObject *args; 424 PyObject *args;
425 PyObject *keyw; 425 PyObject *keyw;
426 PyThreadState *tstate; 426 PyThreadState *tstate;
427 }; 427 };
428 428
429 static void 429 static void
430 t_bootstrap(void *boot_raw) 430 t_bootstrap(void *boot_raw)
431 { 431 {
432 struct bootstate *boot = (struct bootstate *) boot_raw; 432 struct bootstate *boot = (struct bootstate *) boot_raw;
433 PyThreadState *tstate; 433 PyThreadState *tstate;
434 PyObject *res; 434 PyObject *res;
435 435
436 tstate = boot->tstate; 436 tstate = boot->tstate;
437 tstate->thread_id = PyThread_get_thread_ident(); 437 tstate->thread_id = PyThread_get_thread_ident();
438 _PyThreadState_Init(tstate); 438 _PyThreadState_Init(tstate);
439 PyEval_AcquireThread(tstate); 439 PyEval_AcquireThread(tstate);
440 res = PyEval_CallObjectWithKeywords( 440 res = PyEval_CallObjectWithKeywords(
441 boot->func, boot->args, boot->keyw); 441 boot->func, boot->args, boot->keyw);
442 if (res == NULL) { 442 if (res == NULL) {
443 if (PyErr_ExceptionMatches(PyExc_SystemExit)) 443 if (PyErr_ExceptionMatches(PyExc_SystemExit))
444 PyErr_Clear(); 444 PyErr_Clear();
445 else { 445 else {
446 PyObject *file; 446 PyObject *file;
447 PySys_WriteStderr( 447 PySys_WriteStderr(
448 "Unhandled exception in thread started by "); 448 "Unhandled exception in thread started by ");
449 file = PySys_GetObject("stderr"); 449 file = PySys_GetObject("stderr");
450 if (file != NULL && file != Py_None) 450 if (file != NULL && file != Py_None)
451 PyFile_WriteObject(boot->func, file, 0); 451 PyFile_WriteObject(boot->func, file, 0);
452 else 452 else
453 PyObject_Print(boot->func, stderr, 0); 453 PyObject_Print(boot->func, stderr, 0);
454 PySys_WriteStderr("\n"); 454 PySys_WriteStderr("\n");
455 PyErr_PrintEx(0); 455 PyErr_PrintEx(0);
456 } 456 }
457 } 457 }
458 else 458 else
459 Py_DECREF(res); 459 Py_DECREF(res);
460 Py_DECREF(boot->func); 460 Py_DECREF(boot->func);
461 Py_DECREF(boot->args); 461 Py_DECREF(boot->args);
462 Py_XDECREF(boot->keyw); 462 Py_XDECREF(boot->keyw);
463 PyMem_DEL(boot_raw); 463 PyMem_DEL(boot_raw);
464 PyThreadState_Clear(tstate); 464 PyThreadState_Clear(tstate);
465 PyThreadState_DeleteCurrent(); 465 PyThreadState_DeleteCurrent();
466 PyThread_exit_thread(); 466 PyThread_exit_thread();
467 } 467 }
468 468
469 static PyObject * 469 static PyObject *
470 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) 470 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
471 { 471 {
472 PyObject *func, *args, *keyw = NULL; 472 PyObject *func, *args, *keyw = NULL;
473 struct bootstate *boot; 473 struct bootstate *boot;
474 long ident; 474 long ident;
475 475
476 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, 476 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
477 &func, &args, &keyw)) 477 &func, &args, &keyw))
478 return NULL; 478 return NULL;
479 if (!PyCallable_Check(func)) { 479 if (!PyCallable_Check(func)) {
480 PyErr_SetString(PyExc_TypeError, 480 PyErr_SetString(PyExc_TypeError,
481 "first arg must be callable"); 481 "first arg must be callable");
482 return NULL; 482 return NULL;
483 } 483 }
484 if (!PyTuple_Check(args)) { 484 if (!PyTuple_Check(args)) {
485 PyErr_SetString(PyExc_TypeError, 485 PyErr_SetString(PyExc_TypeError,
486 "2nd arg must be a tuple"); 486 "2nd arg must be a tuple");
487 return NULL; 487 return NULL;
488 } 488 }
489 if (keyw != NULL && !PyDict_Check(keyw)) { 489 if (keyw != NULL && !PyDict_Check(keyw)) {
490 PyErr_SetString(PyExc_TypeError, 490 PyErr_SetString(PyExc_TypeError,
491 "optional 3rd arg must be a dictionary"); 491 "optional 3rd arg must be a dictionary");
492 return NULL; 492 return NULL;
493 } 493 }
494 boot = PyMem_NEW(struct bootstate, 1); 494 boot = PyMem_NEW(struct bootstate, 1);
495 if (boot == NULL) 495 if (boot == NULL)
496 return PyErr_NoMemory(); 496 return PyErr_NoMemory();
497 boot->interp = PyThreadState_GET()->interp; 497 boot->interp = PyThreadState_GET()->interp;
498 boot->func = func; 498 boot->func = func;
499 boot->args = args; 499 boot->args = args;
500 boot->keyw = keyw; 500 boot->keyw = keyw;
501 boot->tstate = _PyThreadState_Prealloc(boot->interp); 501 boot->tstate = _PyThreadState_Prealloc(boot->interp);
502 if (boot->tstate == NULL) { 502 if (boot->tstate == NULL) {
503 PyMem_DEL(boot); 503 PyMem_DEL(boot);
504 return PyErr_NoMemory(); 504 return PyErr_NoMemory();
505 } 505 }
506 Py_INCREF(func); 506 Py_INCREF(func);
507 Py_INCREF(args); 507 Py_INCREF(args);
508 Py_XINCREF(keyw); 508 Py_XINCREF(keyw);
509 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ 509 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
510 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot); 510 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
511 if (ident == -1) { 511 if (ident == -1) {
512 PyErr_SetString(ThreadError, "can't start new thread"); 512 PyErr_SetString(ThreadError, "can't start new thread");
513 Py_DECREF(func); 513 Py_DECREF(func);
514 Py_DECREF(args); 514 Py_DECREF(args);
515 Py_XDECREF(keyw); 515 Py_XDECREF(keyw);
516 PyThreadState_Clear(boot->tstate); 516 PyThreadState_Clear(boot->tstate);
517 PyMem_DEL(boot); 517 PyMem_DEL(boot);
518 return NULL; 518 return NULL;
519 } 519 }
520 return PyLong_FromLong(ident); 520 return PyLong_FromLong(ident);
521 } 521 }
522 522
523 PyDoc_STRVAR(start_new_doc, 523 PyDoc_STRVAR(start_new_doc,
524 "start_new_thread(function, args[, kwargs])\n\ 524 "start_new_thread(function, args[, kwargs])\n\
525 (start_new() is an obsolete synonym)\n\ 525 (start_new() is an obsolete synonym)\n\
532 printed unless the exception is SystemExit.\n"); 532 printed unless the exception is SystemExit.\n");
533 533
534 static PyObject * 534 static PyObject *
535 thread_PyThread_exit_thread(PyObject *self) 535 thread_PyThread_exit_thread(PyObject *self)
536 { 536 {
537 PyErr_SetNone(PyExc_SystemExit); 537 PyErr_SetNone(PyExc_SystemExit);
538 return NULL; 538 return NULL;
539 } 539 }
540 540
541 PyDoc_STRVAR(exit_doc, 541 PyDoc_STRVAR(exit_doc,
542 "exit()\n\ 542 "exit()\n\
543 (PyThread_exit_thread() is an obsolete synonym)\n\ 543 (PyThread_exit_thread() is an obsolete synonym)\n\
546 thread to exit silently unless the exception is caught."); 546 thread to exit silently unless the exception is caught.");
547 547
548 static PyObject * 548 static PyObject *
549 thread_PyThread_interrupt_main(PyObject * self) 549 thread_PyThread_interrupt_main(PyObject * self)
550 { 550 {
551 PyErr_SetInterrupt(); 551 PyErr_SetInterrupt();
552 Py_INCREF(Py_None); 552 Py_INCREF(Py_None);
553 return Py_None; 553 return Py_None;
554 } 554 }
555 555
556 PyDoc_STRVAR(interrupt_doc, 556 PyDoc_STRVAR(interrupt_doc,
557 "interrupt_main()\n\ 557 "interrupt_main()\n\
558 \n\ 558 \n\
562 562
563 #ifndef NO_EXIT_PROG 563 #ifndef NO_EXIT_PROG
564 static PyObject * 564 static PyObject *
565 thread_PyThread_exit_prog(PyObject *self, PyObject *args) 565 thread_PyThread_exit_prog(PyObject *self, PyObject *args)
566 { 566 {
567 int sts; 567 int sts;
568 if (!PyArg_ParseTuple(args, "i:exit_prog", &sts)) 568 if (!PyArg_ParseTuple(args, "i:exit_prog", &sts))
569 return NULL; 569 return NULL;
570 Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */ 570 Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */
571 for (;;) { } /* Should not be reached */ 571 for (;;) { } /* Should not be reached */
572 } 572 }
573 #endif 573 #endif
574 574
575 static lockobject *newlockobject(void); 575 static lockobject *newlockobject(void);
576 576
577 static PyObject * 577 static PyObject *
578 thread_PyThread_allocate_lock(PyObject *self) 578 thread_PyThread_allocate_lock(PyObject *self)
579 { 579 {
580 return (PyObject *) newlockobject(); 580 return (PyObject *) newlockobject();
581 } 581 }
582 582
583 PyDoc_STRVAR(allocate_doc, 583 PyDoc_STRVAR(allocate_doc,
584 "allocate_lock() -> lock object\n\ 584 "allocate_lock() -> lock object\n\
585 (allocate() is an obsolete synonym)\n\ 585 (allocate() is an obsolete synonym)\n\
587 Create a new lock object. See LockType.__doc__ for information about locks."); 587 Create a new lock object. See LockType.__doc__ for information about locks.");
588 588
589 static PyObject * 589 static PyObject *
590 thread_get_ident(PyObject *self) 590 thread_get_ident(PyObject *self)
591 { 591 {
592 long ident; 592 long ident;
593 ident = PyThread_get_thread_ident(); 593 ident = PyThread_get_thread_ident();
594 if (ident == -1) { 594 if (ident == -1) {
595 PyErr_SetString(ThreadError, "no current thread ident"); 595 PyErr_SetString(ThreadError, "no current thread ident");
596 return NULL; 596 return NULL;
597 } 597 }
598 return PyLong_FromLong(ident); 598 return PyLong_FromLong(ident);
599 } 599 }
600 600
601 PyDoc_STRVAR(get_ident_doc, 601 PyDoc_STRVAR(get_ident_doc,
602 "get_ident() -> integer\n\ 602 "get_ident() -> integer\n\
603 \n\ 603 \n\
610 A thread's identity may be reused for another thread after it exits."); 610 A thread's identity may be reused for another thread after it exits.");
611 611
612 static PyObject * 612 static PyObject *
613 thread_stack_size(PyObject *self, PyObject *args) 613 thread_stack_size(PyObject *self, PyObject *args)
614 { 614 {
615 size_t old_size; 615 size_t old_size;
616 Py_ssize_t new_size = 0; 616 Py_ssize_t new_size = 0;
617 int rc; 617 int rc;
618 618
619 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size)) 619 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
620 return NULL; 620 return NULL;
621 621
622 if (new_size < 0) { 622 if (new_size < 0) {
623 PyErr_SetString(PyExc_ValueError, 623 PyErr_SetString(PyExc_ValueError,
624 "size must be 0 or a positive value"); 624 "size must be 0 or a positive value");
625 return NULL; 625 return NULL;
626 } 626 }
627 627
628 old_size = PyThread_get_stacksize(); 628 old_size = PyThread_get_stacksize();
629 629
630 rc = PyThread_set_stacksize((size_t) new_size); 630 rc = PyThread_set_stacksize((size_t) new_size);
631 if (rc == -1) { 631 if (rc == -1) {
632 PyErr_Format(PyExc_ValueError, 632 PyErr_Format(PyExc_ValueError,
633 "size not valid: %zd bytes", 633 "size not valid: %zd bytes",
634 new_size); 634 new_size);
635 return NULL; 635 return NULL;
636 } 636 }
637 if (rc == -2) { 637 if (rc == -2) {
638 PyErr_SetString(ThreadError, 638 PyErr_SetString(ThreadError,
639 "setting stack size not supported"); 639 "setting stack size not supported");
640 return NULL; 640 return NULL;
641 } 641 }
642 642
643 return PyLong_FromSsize_t((Py_ssize_t) old_size); 643 return PyLong_FromSsize_t((Py_ssize_t) old_size);
644 } 644 }
645 645
646 PyDoc_STRVAR(stack_size_doc, 646 PyDoc_STRVAR(stack_size_doc,
647 "stack_size([size]) -> size\n\ 647 "stack_size([size]) -> size\n\
648 \n\ 648 \n\
662 - platform documentation should be referred to for more information\n\ 662 - platform documentation should be referred to for more information\n\
663 (4kB pages are common; using multiples of 4096 for the stack size is\n\ 663 (4kB pages are common; using multiples of 4096 for the stack size is\n\
664 the suggested approach in the absence of more specific information)."); 664 the suggested approach in the absence of more specific information).");
665 665
666 static PyMethodDef thread_methods[] = { 666 static PyMethodDef thread_methods[] = {
667 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, 667 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
668 METH_VARARGS, 668 METH_VARARGS,
669 start_new_doc}, 669 start_new_doc},
670 {"start_new", (PyCFunction)thread_PyThread_start_new_thread, 670 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
671 METH_VARARGS, 671 METH_VARARGS,
672 start_new_doc}, 672 start_new_doc},
673 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock, 673 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
674 METH_NOARGS, allocate_doc}, 674 METH_NOARGS, allocate_doc},
675 {"allocate", (PyCFunction)thread_PyThread_allocate_lock, 675 {"allocate", (PyCFunction)thread_PyThread_allocate_lock,
676 METH_NOARGS, allocate_doc}, 676 METH_NOARGS, allocate_doc},
677 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread, 677 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread,
678 METH_NOARGS, exit_doc}, 678 METH_NOARGS, exit_doc},
679 {"exit", (PyCFunction)thread_PyThread_exit_thread, 679 {"exit", (PyCFunction)thread_PyThread_exit_thread,
680 METH_NOARGS, exit_doc}, 680 METH_NOARGS, exit_doc},
681 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main, 681 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
682 METH_NOARGS, interrupt_doc}, 682 METH_NOARGS, interrupt_doc},
683 {"get_ident", (PyCFunction)thread_get_ident, 683 {"get_ident", (PyCFunction)thread_get_ident,
684 METH_NOARGS, get_ident_doc}, 684 METH_NOARGS, get_ident_doc},
685 {"stack_size", (PyCFunction)thread_stack_size, 685 {"stack_size", (PyCFunction)thread_stack_size,
686 METH_VARARGS, 686 METH_VARARGS,
687 stack_size_doc}, 687 stack_size_doc},
688 #ifndef NO_EXIT_PROG 688 #ifndef NO_EXIT_PROG
689 {"exit_prog", (PyCFunction)thread_PyThread_exit_prog, 689 {"exit_prog", (PyCFunction)thread_PyThread_exit_prog,
690 METH_VARARGS}, 690 METH_VARARGS},
691 #endif 691 #endif
692 {NULL, NULL} /* sentinel */ 692 {NULL, NULL} /* sentinel */
693 }; 693 };
694 694
695 695
696 /* Initialization function */ 696 /* Initialization function */
697 697
710 A lock is not owned by the thread that locked it; another thread may\n\ 710 A lock is not owned by the thread that locked it; another thread may\n\
711 unlock it. A thread attempting to lock a lock that it has already locked\n\ 711 unlock it. A thread attempting to lock a lock that it has already locked\n\
712 will block until another thread unlocks it. Deadlocks may ensue."); 712 will block until another thread unlocks it. Deadlocks may ensue.");
713 713
714 static struct PyModuleDef threadmodule = { 714 static struct PyModuleDef threadmodule = {
715 PyModuleDef_HEAD_INIT, 715 PyModuleDef_HEAD_INIT,
716 "_thread", 716 "_thread",
717 thread_doc, 717 thread_doc,
718 -1, 718 -1,
719 thread_methods, 719 thread_methods,
720 NULL, 720 NULL,
721 NULL, 721 NULL,
722 NULL, 722 NULL,
723 NULL 723 NULL
724 }; 724 };
725 725
726 726
727 PyMODINIT_FUNC 727 PyMODINIT_FUNC
728 PyInit__thread(void) 728 PyInit__thread(void)
729 { 729 {
730 PyObject *m, *d; 730 PyObject *m, *d;
731 731
732 /* Initialize types: */ 732 /* Initialize types: */
733 if (PyType_Ready(&localtype) < 0) 733 if (PyType_Ready(&localtype) < 0)
734 return NULL; 734 return NULL;
735 if (PyType_Ready(&Locktype) < 0) 735 if (PyType_Ready(&Locktype) < 0)
736 return NULL; 736 return NULL;
737 737
738 /* Create the module and add the functions */ 738 /* Create the module and add the functions */
739 m = PyModule_Create(&threadmodule); 739 m = PyModule_Create(&threadmodule);
740 if (m == NULL) 740 if (m == NULL)
741 return NULL; 741 return NULL;
742 742
743 /* Add a symbolic constant */ 743 /* Add a symbolic constant */
744 d = PyModule_GetDict(m); 744 d = PyModule_GetDict(m);
745 ThreadError = PyErr_NewException("_thread.error", NULL, NULL); 745 ThreadError = PyErr_NewException("_thread.error", NULL, NULL);
746 PyDict_SetItemString(d, "error", ThreadError); 746 PyDict_SetItemString(d, "error", ThreadError);
747 Locktype.tp_doc = lock_doc; 747 Locktype.tp_doc = lock_doc;
748 Py_INCREF(&Locktype); 748 Py_INCREF(&Locktype);
749 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); 749 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
750 750
751 Py_INCREF(&localtype); 751 Py_INCREF(&localtype);
752 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) 752 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
753 return NULL; 753 return NULL;
754 754
755 /* Initialize the C thread library */ 755 /* Initialize the C thread library */
756 PyThread_init_thread(); 756 PyThread_init_thread();
757 return m; 757 return m;
758 } 758 }