Commit 433aa81e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Fix subclasses of threading.local

Surprisingly, setting tp_getattr and tp_getattro have pretty different behavior;
we can kind of make tp_getattro work with subclassing but apparently don't
do very will with tp_getattr.

Punt on fixing that for now and switch thread._local to use getattro

Class slot handling is getting pretty messy
parent 9ebceb76
...@@ -177,9 +177,9 @@ public: ...@@ -177,9 +177,9 @@ public:
return None; return None;
} }
static int setattr(Box* obj, char* name, Box* val) noexcept { static int setattro(Box* obj, Box* name, Box* val) noexcept {
try { try {
setattrPyston(obj, boxString(name), val); setattrPyston(obj, name, val);
} catch (ExcInfo e) { } catch (ExcInfo e) {
setCAPIException(e); setCAPIException(e);
return -1; return -1;
...@@ -187,18 +187,21 @@ public: ...@@ -187,18 +187,21 @@ public:
return 0; return 0;
} }
static Box* getattr(Box* obj, char* name) noexcept { static Box* getattro(Box* obj, Box* name) noexcept {
assert(name->cls == str_cls);
llvm::StringRef s = static_cast<BoxedString*>(name)->s;
Box* tls_obj = getThreadLocalObject(obj); Box* tls_obj = getThreadLocalObject(obj);
if (!strcmp(name, "__dict__")) if (s == "__dict__")
return tls_obj; return tls_obj;
try { try {
return getitem(tls_obj, boxString(name)); return getitem(tls_obj, name);
} catch (ExcInfo e) { } catch (ExcInfo e) {
} }
try { try {
Box* r = getattrInternalGeneric(obj, name, NULL, false, false, NULL, NULL); Box* r = getattrInternalGeneric(obj, s, NULL, false, false, NULL, NULL);
if (r) if (r)
return r; return r;
} catch (ExcInfo e) { } catch (ExcInfo e) {
...@@ -206,7 +209,7 @@ public: ...@@ -206,7 +209,7 @@ public:
return NULL; return NULL;
} }
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", Py_TYPE(obj)->tp_name, name); PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", Py_TYPE(obj)->tp_name, s.data());
return NULL; return NULL;
} }
...@@ -249,18 +252,20 @@ void setupThread() { ...@@ -249,18 +252,20 @@ void setupThread() {
thread_lock_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::exit, NONE, 4))); thread_lock_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::exit, NONE, 4)));
thread_lock_cls->freeze(); thread_lock_cls->freeze();
thread_local_cls thread_local_cls = new (0) BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedThreadLocal), false,
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedThreadLocal), false, "_local"); static_cast<BoxedString*>(boxString("_local")));
thread_local_cls->giveAttr("__module__", boxStrConstant("thread")); thread_local_cls->giveAttr("__module__", boxStrConstant("thread"));
thread_local_cls->giveAttr("__hash__", thread_local_cls->giveAttr("__hash__",
new BoxedFunction(boxRTFunction((void*)BoxedThreadLocal::hash, BOXED_INT, 1))); new BoxedFunction(boxRTFunction((void*)BoxedThreadLocal::hash, BOXED_INT, 1)));
thread_local_cls->giveAttr("__setattr__", thread_local_cls->giveAttr("__setattr__",
new BoxedFunction(boxRTFunction((void*)BoxedThreadLocal::setattrPyston, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)BoxedThreadLocal::setattrPyston, UNKNOWN, 3)));
thread_local_cls->freeze();
thread_module->giveAttr("_local", thread_local_cls); thread_module->giveAttr("_local", thread_local_cls);
thread_local_cls->tp_setattr = BoxedThreadLocal::setattr; thread_local_cls->tp_setattro = BoxedThreadLocal::setattro;
thread_local_cls->tp_getattr = BoxedThreadLocal::getattr; thread_local_cls->tp_getattro = BoxedThreadLocal::getattro;
add_operators(thread_local_cls);
thread_local_cls->finishInitialization();
thread_local_cls->freeze();
BoxedClass* ThreadError BoxedClass* ThreadError
= BoxedHeapClass::create(type_cls, Exception, NULL, Exception->attrs_offset, Exception->tp_weaklistoffset, = BoxedHeapClass::create(type_cls, Exception, NULL, Exception->attrs_offset, Exception->tp_weaklistoffset,
......
...@@ -223,6 +223,7 @@ protected: ...@@ -223,6 +223,7 @@ protected:
friend void setupRuntime(); friend void setupRuntime();
friend void setupSysEnd(); friend void setupSysEnd();
friend void setupThread();
}; };
class BoxedHeapClass : public BoxedClass { class BoxedHeapClass : public BoxedClass {
...@@ -256,6 +257,7 @@ private: ...@@ -256,6 +257,7 @@ private:
friend void setupRuntime(); friend void setupRuntime();
friend void setupSys(); friend void setupSys();
friend void setupThread();
DEFAULT_CLASS_VAR(type_cls, sizeof(SlotOffset)); DEFAULT_CLASS_VAR(type_cls, sizeof(SlotOffset));
}; };
......
...@@ -4,9 +4,21 @@ import threading ...@@ -4,9 +4,21 @@ import threading
a = threading.local() a = threading.local()
a.x = "hello world" a.x = "hello world"
class CustomThreadingLocal(threading.local):
n = 0
def __init__(self):
print "__init__", self.n
self.a = self.n
self.n += 1
print self.a, self.n
print CustomThreadingLocal().a
print CustomThreadingLocal().a
def f(): def f():
a.x = "goodbye world" a.x = "goodbye world"
print a.x print a.x
print CustomThreadingLocal().a
print CustomThreadingLocal().a
def test(): def test():
thread = threading.Thread(target=f) thread = threading.Thread(target=f)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment