| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |