| 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) |
|
Antoine Pitrou
2008/08/28 09:29:49
A Py_DECREF(localdict) is needed just before baili
gregory.p.smith
2008/09/02 06:43:30
On 2008/08/28 09:29:49, Antoine Pitrou wrote:
> A
| |
| 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 else if (self->dict != ldict) { | |
| 297 Py_CLEAR(self->dict); | |
| 298 Py_INCREF(ldict); | |
| 299 self->dict = ldict; | |
| 300 } | 290 } |
| 301 | 291 |
| 302 return ldict; | 292 return ldict; |
| 303 } | 293 } |
| 304 | 294 |
| 305 static int | 295 static int |
| 306 local_setattro(localobject *self, PyObject *name, PyObject *v) | 296 local_setattro(localobject *self, PyObject *name, PyObject *v) |
| 307 { | 297 { |
| 308 » PyObject *ldict; | 298 » int res = PyObject_GenericSetAttr((PyObject *)self, name, v); |
| 309 » | |
| 310 » ldict = _ldict(self); | |
| 311 » if (ldict == NULL) | |
| 312 » » return -1; | |
| 313 | 299 |
| 314 » return PyObject_GenericSetAttr((PyObject *)self, name, v); | 300 » if (res < 0 && PyErr_ExceptionMatches(PyExc_AttributeError)) { |
|
Antoine Pitrou
2008/08/28 09:29:49
Why did you add this fallback? Is it really necess
gregory.p.smith
2008/09/02 06:43:30
On 2008/08/28 09:29:49, Antoine Pitrou wrote:
> Wh
| |
| 301 » » PyObject *ldict = _ldict(self); | |
| 302 » » if (ldict == NULL) | |
| 303 » » » return -1; | |
| 304 | |
| 305 » » PyErr_Clear(); | |
| 306 | |
| 307 » » res = PyDict_SetItem(ldict, name, v); | |
| 308 » } | |
| 309 | |
| 310 » return res; | |
| 315 } | 311 } |
| 316 | 312 |
| 317 static PyObject * | 313 static PyObject * |
| 318 local_getdict(localobject *self, void *closure) | 314 local_getdict(localobject *self, void *closure) |
| 319 { | 315 { |
| 320 » if (self->dict == NULL) { | 316 » PyObject *ldict = _ldict(self); |
| 317 » if (ldict == NULL) { | |
| 321 PyErr_SetString(PyExc_AttributeError, "__dict__"); | 318 PyErr_SetString(PyExc_AttributeError, "__dict__"); |
| 322 return NULL; | 319 return NULL; |
| 323 } | 320 } |
| 324 | 321 |
| 325 » Py_INCREF(self->dict); | 322 » Py_INCREF(ldict); |
| 326 » return self->dict; | 323 » return ldict; |
| 327 } | 324 } |
| 328 | 325 |
| 329 static PyGetSetDef local_getset[] = { | 326 static PyGetSetDef local_getset[] = { |
| 330 {"__dict__", (getter)local_getdict, (setter)NULL, | 327 {"__dict__", (getter)local_getdict, (setter)NULL, |
| 331 "Local-data dictionary", NULL}, | 328 "Local-data dictionary", NULL}, |
| 332 {NULL} /* Sentinel */ | 329 {NULL} /* Sentinel */ |
| 333 }; | 330 }; |
| 334 | 331 |
| 335 static PyObject *local_getattro(localobject *, PyObject *); | 332 static PyObject *local_getattro(localobject *, PyObject *); |
| 336 | 333 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 362 /* tp_weaklistoffset */ 0, | 359 /* tp_weaklistoffset */ 0, |
| 363 /* tp_iter */ 0, | 360 /* tp_iter */ 0, |
| 364 /* tp_iternext */ 0, | 361 /* tp_iternext */ 0, |
| 365 /* tp_methods */ 0, | 362 /* tp_methods */ 0, |
| 366 /* tp_members */ 0, | 363 /* tp_members */ 0, |
| 367 /* tp_getset */ local_getset, | 364 /* tp_getset */ local_getset, |
| 368 /* tp_base */ 0, | 365 /* tp_base */ 0, |
| 369 /* tp_dict */ 0, /* internal use */ | 366 /* tp_dict */ 0, /* internal use */ |
| 370 /* tp_descr_get */ 0, | 367 /* tp_descr_get */ 0, |
| 371 /* tp_descr_set */ 0, | 368 /* tp_descr_set */ 0, |
| 372 » /* tp_dictoffset */ offsetof(localobject, dict), | 369 » /* tp_dictoffset */ 0, |
| 373 /* tp_init */ 0, | 370 /* tp_init */ 0, |
| 374 /* tp_alloc */ 0, | 371 /* tp_alloc */ 0, |
| 375 /* tp_new */ local_new, | 372 /* tp_new */ local_new, |
| 376 /* tp_free */ 0, /* Low-level free-mem routine */ | 373 /* tp_free */ 0, /* Low-level free-mem routine */ |
| 377 /* tp_is_gc */ 0, /* For PyObject_IS_GC */ | 374 /* tp_is_gc */ 0, /* For PyObject_IS_GC */ |
| 378 }; | 375 }; |
| 379 | 376 |
| 380 static PyObject * | 377 static PyObject * |
| 381 local_getattro(localobject *self, PyObject *name) | 378 local_getattro(localobject *self, PyObject *name) |
| 382 { | 379 { |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 709 Py_INCREF(&Locktype); | 706 Py_INCREF(&Locktype); |
| 710 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); | 707 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); |
| 711 | 708 |
| 712 Py_INCREF(&localtype); | 709 Py_INCREF(&localtype); |
| 713 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) | 710 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) |
| 714 return; | 711 return; |
| 715 | 712 |
| 716 /* Initialize the C thread library */ | 713 /* Initialize the C thread library */ |
| 717 PyThread_init_thread(); | 714 PyThread_init_thread(); |
| 718 } | 715 } |
| OLD | NEW |