|
From: <pj...@us...> - 2011-01-21 01:18:41
|
Revision: 7186
http://jython.svn.sourceforge.net/jython/?rev=7186&view=rev
Author: pjenvey
Date: 2011-01-21 01:18:35 +0000 (Fri, 21 Jan 2011)
Log Message:
-----------
o fix threading.local subclassing problems with __init__ arguments
o fastGetDict doesn't need to synchronize around a ThreadLocal initialization
fixes #1667
thanks Kelly Campbell
Modified Paths:
--------------
trunk/jython/NEWS
trunk/jython/src/org/python/modules/thread/PyLocal.java
Added Paths:
-----------
trunk/jython/Lib/test/test_threading_local_jy.py
Added: trunk/jython/Lib/test/test_threading_local_jy.py
===================================================================
--- trunk/jython/Lib/test/test_threading_local_jy.py (rev 0)
+++ trunk/jython/Lib/test/test_threading_local_jy.py 2011-01-21 01:18:35 UTC (rev 7186)
@@ -0,0 +1,61 @@
+"""Test for thread locals"""
+import random
+import sys
+import threading
+import time
+import unittest
+from test import test_support
+from threading import local
+
+class LocalStuff(local):
+ def __init__(self, stuff, foo=1):
+ local.__init__(self)
+ self.stuff = stuff
+ self.foo = foo
+
+class TestThread(threading.Thread):
+ def __init__(self, stuff, name):
+ threading.Thread.__init__(self)
+ self.stuff = stuff
+ self.name = name
+ self.errors = []
+
+ def run(self):
+ for i in xrange(10):
+ try:
+ self.stuff.stuff = self.name
+ myStuff = self.stuff.stuff
+ time.sleep(random.random() * 2)
+ if myStuff != self.stuff.stuff:
+ self.errors.append("myStuff should equal self.stuff.stuff")
+ if self.stuff.foo != 1:
+ self.errors.append("foo should be 1")
+ except TypeError, te:
+ self.errors.append("TypeError: %s" % te)
+ except:
+ self.errors.append("unexpected error: %s" % sys.exc_info()[0] )
+
+ def getErrors(self):
+ return self.errors
+
+class ThreadLocalConstructorTestCase(unittest.TestCase):
+
+ def test_construct_locals(self):
+ """Ensures that constructing a local can have arguments"""
+ stuff = LocalStuff("main stuff")
+ threads = []
+ for i in xrange(20):
+ threads.append(TestThread(stuff, name=("thread-%d" % i)))
+ threads[i].start()
+ for i in xrange(20):
+ threads[i].join()
+ errors = threads[i].getErrors()
+ self.assertEquals(0, len(errors), errors)
+
+
+def test_main():
+ test_support.run_unittest(ThreadLocalConstructorTestCase)
+
+
+if __name__ == "__main__":
+ test_main()
Modified: trunk/jython/NEWS
===================================================================
--- trunk/jython/NEWS 2011-01-10 23:29:19 UTC (rev 7185)
+++ trunk/jython/NEWS 2011-01-21 01:18:35 UTC (rev 7186)
@@ -1,5 +1,9 @@
Jython NEWS
+Jython 2.5.2
+ Bugs Fixed
+ - [ 1667 ] thread.local subclasses with constructor params fail
+
Jython 2.5.2rc3
Bugs Fixed
- [ 1674 ] PDB crashes under the JSR-223 scripting engine
Modified: trunk/jython/src/org/python/modules/thread/PyLocal.java
===================================================================
--- trunk/jython/src/org/python/modules/thread/PyLocal.java 2011-01-10 23:29:19 UTC (rev 7185)
+++ trunk/jython/src/org/python/modules/thread/PyLocal.java 2011-01-21 01:18:35 UTC (rev 7186)
@@ -1,3 +1,4 @@
+/* Copyright (c) Jython Developers */
package org.python.modules.thread;
import org.python.core.Py;
@@ -6,7 +7,6 @@
import org.python.core.PyObject;
import org.python.core.PyType;
import org.python.expose.ExposedGet;
-import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedSet;
import org.python.expose.ExposedType;
@@ -28,9 +28,8 @@
public PyLocal(PyType subType) {
super(subType);
- // Because the instantiation of a type instance in PyType.invoke_new_
- // calls dispatch__init__, we call tdict.set here so dispatch__init__
- // doesn't get called a second time for a thread in fastGetDict
+ // Don't lazy load the underlying dict in the insantiating thread; that would call
+ // __init__ a the second time
tdict.set(new PyDictionary());
}
@@ -40,29 +39,24 @@
PyType subtype,
PyObject[] args,
String[] keywords) {
+ PyObject[] where = new PyObject[1];
+ subtype.lookup_where("__init__", where);
+ if (where[0] == PyObject.TYPE && args.length > 0) {
+ throw Py.TypeError("Initialization arguments are not supported");
+ }
+
PyLocal newobj;
if (new_.getWrappedType() == subtype) {
newobj = new PyLocal();
} else {
newobj = new PyLocalDerived(subtype);
}
- if (init) {
- newobj._local___init__(args, keywords);
- }
+ newobj.args = args;
+ newobj.keywords = keywords;
+
return newobj;
}
- @ExposedMethod
- final void _local___init__(PyObject[] args, String[] keywords) {
- PyObject[] where = new PyObject[1];
- getType().lookup_where("__init__", where);
- if (where[0] == TYPE && args.length > 0) {
- throw Py.TypeError("Initialization arguments are not supported");
- }
- this.args = args;
- this.keywords = keywords;
- }
-
@Override
@ExposedGet(name = "__dict__")
public PyObject getDict() {
@@ -76,7 +70,7 @@
}
@Override
- public synchronized PyObject fastGetDict() {
+ public PyObject fastGetDict() {
PyDictionary ldict = tdict.get();
if (ldict == null) {
ldict = new PyDictionary();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|