From: <zy...@us...> - 2010-07-14 05:12:26
|
Revision: 7078 http://jython.svn.sourceforge.net/jython/?rev=7078&view=rev Author: zyasoft Date: 2010-07-14 05:12:19 +0000 (Wed, 14 Jul 2010) Log Message: ----------- Added specific support of threading.Thread.__tojava__, which enables the underlying Java thread to be accessed. Also restored concurrency of the canonical maps by switching to Google Guava to support them with MapMaker. Fixes #1630. Modified Paths: -------------- trunk/jython/Lib/test/test_threading_jy.py trunk/jython/Lib/threading.py trunk/jython/NEWS trunk/jython/src/org/python/modules/_threading/_threading.java Modified: trunk/jython/Lib/test/test_threading_jy.py =================================================================== --- trunk/jython/Lib/test/test_threading_jy.py 2010-07-14 04:18:08 UTC (rev 7077) +++ trunk/jython/Lib/test/test_threading_jy.py 2010-07-14 05:12:19 UTC (rev 7078) @@ -2,13 +2,17 @@ Made for Jython. """ +from __future__ import with_statement + import unittest from test import test_support import threading import time import random -from threading import Thread +from threading import Condition, Lock, Thread +from java.lang import Thread as JThread, InterruptedException + class ThreadingTestCase(unittest.TestCase): def test_str_name(self): @@ -42,8 +46,46 @@ self.assertEqual(threading.Lock, threading._Lock) self.assertEqual(threading.RLock, threading._RLock) + +class JavaIntegrationTestCase(unittest.TestCase): + """Verifies that Thread.__tojava__ correctly gets the underlying Java thread""" + + def test_interruptible(self): + + def wait_until_interrupted(cv): + name = threading.currentThread().getName() + with cv: + while not JThread.currentThread().isInterrupted(): + try: + cv.wait() + except InterruptedException, e: + break + + num_threads = 5 + unfair_condition = Condition() + threads = [ + Thread( + name="thread #%d" % i, + target=wait_until_interrupted, + args=(unfair_condition,)) + for i in xrange(num_threads)] + + for thread in threads: + thread.start() + time.sleep(0.1) + + for thread in threads: + JThread.interrupt(thread) + + joined_threads = 0 + for thread in threads: + thread.join(1.) # timeout just in case so we don't stall regrtest + joined_threads += 1 + self.assertEqual(joined_threads, num_threads) + + def test_main(): - test_support.run_unittest(ThreadingTestCase, TwistedTestCase) + test_support.run_unittest(JavaIntegrationTestCase, ThreadingTestCase, TwistedTestCase) if __name__ == "__main__": Modified: trunk/jython/Lib/threading.py =================================================================== --- trunk/jython/Lib/threading.py 2010-07-14 04:18:08 UTC (rev 7077) +++ trunk/jython/Lib/threading.py 2010-07-14 05:12:19 UTC (rev 7078) @@ -3,12 +3,11 @@ from java.util.concurrent import Semaphore, CyclicBarrier from java.util.concurrent.locks import ReentrantLock from org.python.util import jython +from org.python.core import Py from thread import _newFunctionThread from thread import _local as local -from _threading import Lock, RLock, Condition, _Lock, _RLock +from _threading import Lock, RLock, Condition, _Lock, _RLock, _threads, _active, _jthread_to_pythread, _register_thread, _unregister_thread import java.lang.Thread -import weakref - import sys as _sys from traceback import print_exc as _print_exc @@ -93,8 +92,7 @@ class JavaThread(object): def __init__(self, thread): self._thread = thread - _jthread_to_pythread[thread] = self - _threads[thread.getId()] = self + _register_thread(thread, self) def __repr__(self): _thread = self._thread @@ -141,11 +139,14 @@ def setDaemon(self, daemonic): self._thread.setDaemon(bool(daemonic)) -# relies on the fact that this is a CHM -_threads = weakref.WeakValueDictionary() -_active = _threads -_jthread_to_pythread = Collections.synchronizedMap(WeakHashMap()) + def __tojava__(self, c): + if isinstance(self._thread, c): + return self._thread + if isinstance(self, c): + return self + return Py.NoConversion + class Thread(JavaThread): def __init__(self, group=None, target=None, name=None, args=None, kwargs=None): assert group is None, "group argument must be None for now" @@ -225,7 +226,7 @@ pass def __delete(self): - del _threads[self._thread.getId()] + _unregister_thread(self._thread) class _MainThread(Thread): @@ -241,7 +242,7 @@ return False def __exitfunc(self): - del _threads[self._thread.getId()] + _unregister_thread(self._thread) t = _pickSomeNonDaemonThread() while t: t.join() Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-07-14 04:18:08 UTC (rev 7077) +++ trunk/jython/NEWS 2010-07-14 05:12:19 UTC (rev 7078) @@ -1,8 +1,8 @@ Jython NEWS -Jython 2.5.2a1 +Jython 2.5.2b2 Bugs Fixed - - [ ] + - [ 1630 ] threading.Thread lacks __tojava__ method Jython 2.5.2b1 Bugs Fixed Modified: trunk/jython/src/org/python/modules/_threading/_threading.java =================================================================== --- trunk/jython/src/org/python/modules/_threading/_threading.java 2010-07-14 04:18:08 UTC (rev 7077) +++ trunk/jython/src/org/python/modules/_threading/_threading.java 2010-07-14 05:12:19 UTC (rev 7078) @@ -3,6 +3,8 @@ import org.python.core.ClassDictInit; import org.python.core.Py; import org.python.core.PyObject; +import com.google.common.collect.MapMaker; +import java.util.Map; public class _threading implements ClassDictInit { @@ -13,5 +15,21 @@ dict.__setitem__("_Lock", Lock.TYPE); dict.__setitem__("_RLock", Lock.TYPE); dict.__setitem__("Condition", Condition.TYPE); +// dict.__setitem__("JavaThread", JavaThread.TYPE); } + + // internals to support threading.py, test_threading.py + public static Map<Long, PyObject> _threads = new MapMaker().weakValues().makeMap(); + public static Map<Thread, PyObject> _jthread_to_pythread = new MapMaker().weakKeys().makeMap(); + public static Map<Long, PyObject> _active = _threads; + + public static void _register_thread(Thread jthread, PyObject pythread) { + _threads.put(jthread.getId(), pythread); + _jthread_to_pythread.put(jthread, pythread); + } + + public static void _unregister_thread(Thread jthread) { + _threads.remove(jthread.getId()); + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |