Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(53)

Side by Side Diff: Modules/threadmodule.c

Issue 3641: thread._local, threading.local Python issue 1868 & 3710 SVN Base: http://svn.python.org/view/*checkout*/python/trunk/
Patch Set: christian heimes updated version Created 1 year, 3 months ago , Downloaded from: http://bugs.python.org/file11297/threading_local2.patch
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* Thread module */ 2 /* Thread module */
3 /* Interface to Sjoerd's portable C thread library */ 3 /* Interface to Sjoerd's portable C thread library */
4 4
5 #include "Python.h" 5 #include "Python.h"
6 6
7 #ifndef WITH_THREAD 7 #ifndef WITH_THREAD
8 #error "Error! The rest of Python is not compiled with thread support." 8 #error "Error! The rest of Python is not compiled with thread support."
9 #error "Rerun configure, adding a --with-threads option." 9 #error "Rerun configure, adding a --with-threads option."
10 #error "Then run `make clean' followed by `make'." 10 #error "Then run `make clean' followed by `make'."
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 157
158 /* Thread-local objects */ 158 /* Thread-local objects */
159 159
160 #include "structmember.h" 160 #include "structmember.h"
161 161
162 typedef struct { 162 typedef struct {
163 PyObject_HEAD 163 PyObject_HEAD
164 PyObject *key; 164 PyObject *key;
165 PyObject *args; 165 PyObject *args;
166 PyObject *kw; 166 PyObject *kw;
167 PyObject *dict;
168 } localobject; 167 } localobject;
169 168
170 static PyObject * 169 static PyObject *
171 local_new(PyTypeObject *type, PyObject *args, PyObject *kw) 170 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
172 { 171 {
173 localobject *self; 172 localobject *self;
174 PyObject *tdict; 173 PyObject *tdict;
174 PyObject *localdict;
175 175
176 if (type->tp_init == PyBaseObject_Type.tp_init 176 if (type->tp_init == PyBaseObject_Type.tp_init
177 && ((args && PyObject_IsTrue(args)) 177 && ((args && PyObject_IsTrue(args))
178 || (kw && PyObject_IsTrue(kw)))) { 178 || (kw && PyObject_IsTrue(kw)))) {
179 PyErr_SetString(PyExc_TypeError, 179 PyErr_SetString(PyExc_TypeError,
180 "Initialization arguments are not supported"); 180 "Initialization arguments are not supported");
181 return NULL; 181 return NULL;
182 } 182 }
183 183
184 self = (localobject *)type->tp_alloc(type, 0); 184 self = (localobject *)type->tp_alloc(type, 0);
185 if (self == NULL) 185 if (self == NULL)
186 return NULL; 186 return NULL;
187 187
188 Py_XINCREF(args); 188 Py_XINCREF(args);
189 self->args = args; 189 self->args = args;
190 Py_XINCREF(kw); 190 Py_XINCREF(kw);
191 self->kw = kw; 191 self->kw = kw;
192 self->dict = NULL; /* making sure */
193 self->key = PyString_FromFormat("thread.local.%p", self); 192 self->key = PyString_FromFormat("thread.local.%p", self);
194 if (self->key == NULL) 193 if (self->key == NULL)
195 goto err; 194 goto err;
196 195
197 » self->dict = PyDict_New(); 196 » localdict = PyDict_New();
198 » if (self->dict == NULL) 197 » if (localdict == NULL)
199 goto err; 198 goto err;
200 199
201 tdict = PyThreadState_GetDict(); 200 tdict = PyThreadState_GetDict();
202 if (tdict == NULL) { 201 if (tdict == NULL) {
203 PyErr_SetString(PyExc_SystemError, 202 PyErr_SetString(PyExc_SystemError,
204 "Couldn't get thread-state dictionary"); 203 "Couldn't get thread-state dictionary");
205 goto err; 204 goto err;
206 } 205 }
207 206
208 » if (PyDict_SetItem(tdict, self->key, self->dict) < 0) 207 » if (PyDict_SetItem(tdict, self->key, localdict) < 0)
209 goto err; 208 goto err;
209 Py_DECREF(localdict);
210 210
211 return (PyObject *)self; 211 return (PyObject *)self;
212 212
213 err: 213 err:
214 Py_DECREF(self); 214 Py_DECREF(self);
215 return NULL; 215 return NULL;
216 } 216 }
217 217
218 static int 218 static int
219 local_traverse(localobject *self, visitproc visit, void *arg) 219 local_traverse(localobject *self, visitproc visit, void *arg)
220 { 220 {
221 Py_VISIT(self->args); 221 Py_VISIT(self->args);
222 Py_VISIT(self->kw); 222 Py_VISIT(self->kw);
223 Py_VISIT(self->dict);
224 return 0; 223 return 0;
225 } 224 }
226 225
227 static int 226 static int
228 local_clear(localobject *self) 227 local_clear(localobject *self)
229 { 228 {
230 Py_CLEAR(self->key); 229 Py_CLEAR(self->key);
231 Py_CLEAR(self->args); 230 Py_CLEAR(self->args);
232 Py_CLEAR(self->kw); 231 Py_CLEAR(self->kw);
233 Py_CLEAR(self->dict);
234 return 0; 232 return 0;
235 } 233 }
236 234
237 static void 235 static void
238 local_dealloc(localobject *self) 236 local_dealloc(localobject *self)
239 { 237 {
240 PyThreadState *tstate; 238 PyThreadState *tstate;
241 if (self->key 239 if (self->key
242 && (tstate = PyThreadState_Get()) 240 && (tstate = PyThreadState_Get())
243 && tstate->interp) { 241 && tstate->interp) {
244 for(tstate = PyInterpreterState_ThreadHead(tstate->interp); 242 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
245 tstate; 243 tstate;
246 tstate = PyThreadState_Next(tstate)) 244 tstate = PyThreadState_Next(tstate))
247 if (tstate->dict && 245 if (tstate->dict &&
248 PyDict_GetItem(tstate->dict, self->key)) 246 PyDict_GetItem(tstate->dict, self->key))
249 PyDict_DelItem(tstate->dict, self->key); 247 PyDict_DelItem(tstate->dict, self->key);
250 } 248 }
251 249
252 local_clear(self); 250 local_clear(self);
253 Py_TYPE(self)->tp_free((PyObject*)self); 251 Py_TYPE(self)->tp_free((PyObject*)self);
254 } 252 }
255 253
254 /* Return borrowed reference to the local dict */
256 static PyObject * 255 static PyObject *
257 _ldict(localobject *self) 256 _ldict(localobject *self)
258 { 257 {
259 PyObject *tdict, *ldict; 258 PyObject *tdict, *ldict;
260 259
261 tdict = PyThreadState_GetDict(); 260 tdict = PyThreadState_GetDict();
262 if (tdict == NULL) { 261 if (tdict == NULL) {
263 PyErr_SetString(PyExc_SystemError, 262 PyErr_SetString(PyExc_SystemError,
264 "Couldn't get thread-state dictionary"); 263 "Couldn't get thread-state dictionary");
265 return NULL; 264 return NULL;
266 } 265 }
267 266
268 ldict = PyDict_GetItem(tdict, self->key); 267 ldict = PyDict_GetItem(tdict, self->key);
269 if (ldict == NULL) { 268 if (ldict == NULL) {
270 ldict = PyDict_New(); /* we own ldict */ 269 ldict = PyDict_New(); /* we own ldict */
271 270
272 if (ldict == NULL) 271 if (ldict == NULL)
273 return NULL; 272 return NULL;
274 else { 273 else {
275 int i = PyDict_SetItem(tdict, self->key, ldict); 274 int i = PyDict_SetItem(tdict, self->key, ldict);
276 Py_DECREF(ldict); /* now ldict is borrowed */ 275 Py_DECREF(ldict); /* now ldict is borrowed */
277 if (i < 0) 276 if (i < 0)
278 return NULL; 277 return NULL;
279 } 278 }
280
281 Py_CLEAR(self->dict);
282 Py_INCREF(ldict);
283 self->dict = ldict; /* still borrowed */
284 279
285 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init && 280 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
286 Py_TYPE(self)->tp_init((PyObject*)self, 281 Py_TYPE(self)->tp_init((PyObject*)self,
287 self->args, self->kw) < 0) { 282 self->args, self->kw) < 0) {
288 /* we need to get rid of ldict from thread so 283 /* we need to get rid of ldict from thread so
289 we create a new one the next time we do an attr 284 we create a new one the next time we do an attr
290 acces */ 285 acces */
291 PyDict_DelItem(tdict, self->key); 286 PyDict_DelItem(tdict, self->key);
292 return NULL; 287 return NULL;
293 } 288 }
294 289
295 }
296
297 /* The call to tp_init above may have caused another thread to run.
298 Install our ldict again. */
299 if (self->dict != ldict) {
300 Py_CLEAR(self->dict);
301 Py_INCREF(ldict);
302 self->dict = ldict;
303 } 290 }
304 291
305 return ldict; 292 return ldict;
306 } 293 }
307 294
308 static int 295 static int
309 local_setattro(localobject *self, PyObject *name, PyObject *v) 296 local_setattro(localobject *self, PyObject *name, PyObject *v)
310 { 297 {
311 » PyObject *ldict; 298 » PyObject *ldict = _ldict(self);
312 »
313 » ldict = _ldict(self);
314 if (ldict == NULL) 299 if (ldict == NULL)
315 return -1; 300 return -1;
316 301
317 » return PyObject_GenericSetAttr((PyObject *)self, name, v); 302 » return PyDict_SetItem(ldict, name, v);
318 } 303 }
319 304
320 static PyObject * 305 static PyObject *
321 local_getdict(localobject *self, void *closure) 306 local_getdict(localobject *self, void *closure)
322 { 307 {
323 » if (self->dict == NULL) { 308 » PyObject *ldict = _ldict(self);
309 » if (ldict == NULL) {
324 PyErr_SetString(PyExc_AttributeError, "__dict__"); 310 PyErr_SetString(PyExc_AttributeError, "__dict__");
325 return NULL; 311 return NULL;
326 } 312 }
327 313
328 » Py_INCREF(self->dict); 314 » Py_INCREF(ldict);
329 » return self->dict; 315 » return ldict;
330 } 316 }
331 317
332 static PyGetSetDef local_getset[] = { 318 static PyGetSetDef local_getset[] = {
333 {"__dict__", (getter)local_getdict, (setter)NULL, 319 {"__dict__", (getter)local_getdict, (setter)NULL,
334 "Local-data dictionary", NULL}, 320 "Local-data dictionary", NULL},
335 {NULL} /* Sentinel */ 321 {NULL} /* Sentinel */
336 }; 322 };
337 323
338 static PyObject *local_getattro(localobject *, PyObject *); 324 static PyObject *local_getattro(localobject *, PyObject *);
339 325
(...skipping 25 matching lines...) Expand all
365 /* tp_weaklistoffset */ 0, 351 /* tp_weaklistoffset */ 0,
366 /* tp_iter */ 0, 352 /* tp_iter */ 0,
367 /* tp_iternext */ 0, 353 /* tp_iternext */ 0,
368 /* tp_methods */ 0, 354 /* tp_methods */ 0,
369 /* tp_members */ 0, 355 /* tp_members */ 0,
370 /* tp_getset */ local_getset, 356 /* tp_getset */ local_getset,
371 /* tp_base */ 0, 357 /* tp_base */ 0,
372 /* tp_dict */ 0, /* internal use */ 358 /* tp_dict */ 0, /* internal use */
373 /* tp_descr_get */ 0, 359 /* tp_descr_get */ 0,
374 /* tp_descr_set */ 0, 360 /* tp_descr_set */ 0,
375 » /* tp_dictoffset */ offsetof(localobject, dict), 361 » /* tp_dictoffset */ 0,
376 /* tp_init */ 0, 362 /* tp_init */ 0,
377 /* tp_alloc */ 0, 363 /* tp_alloc */ 0,
378 /* tp_new */ local_new, 364 /* tp_new */ local_new,
379 /* tp_free */ 0, /* Low-level free-mem routine */ 365 /* tp_free */ 0, /* Low-level free-mem routine */
380 /* tp_is_gc */ 0, /* For PyObject_IS_GC */ 366 /* tp_is_gc */ 0, /* For PyObject_IS_GC */
381 }; 367 };
382 368
383 static PyObject * 369 static PyObject *
384 local_getattro(localobject *self, PyObject *name) 370 local_getattro(localobject *self, PyObject *name)
385 { 371 {
386 PyObject *ldict, *value; 372 PyObject *ldict, *value;
387 373
388 ldict = _ldict(self); 374 ldict = _ldict(self);
389 if (ldict == NULL) 375 if (ldict == NULL)
390 return NULL; 376 return NULL;
391
392 if (Py_TYPE(self) != &localtype)
393 /* use generic lookup for subtypes */
394 return PyObject_GenericGetAttr((PyObject *)self, name);
395 377
396 /* Optimization: just look in dict ourselves */ 378 /* Optimization: just look in dict ourselves */
397 value = PyDict_GetItem(ldict, name); 379 value = PyDict_GetItem(ldict, name);
398 if (value == NULL) 380 if (value == NULL)
399 /* Fall back on generic to get __class__ and __dict__ */ 381 /* Fall back on generic to get __class__ and __dict__ */
400 return PyObject_GenericGetAttr((PyObject *)self, name); 382 return PyObject_GenericGetAttr((PyObject *)self, name);
401 383
402 Py_INCREF(value); 384 Py_INCREF(value);
403 return value; 385 return value;
404 } 386 }
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 Py_INCREF(&Locktype); 694 Py_INCREF(&Locktype);
713 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); 695 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
714 696
715 Py_INCREF(&localtype); 697 Py_INCREF(&localtype);
716 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) 698 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
717 return; 699 return;
718 700
719 /* Initialize the C thread library */ 701 /* Initialize the C thread library */
720 PyThread_init_thread(); 702 PyThread_init_thread();
721 } 703 }
OLDNEW
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r497