]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
threading._DummyThread.__init__(): document obscure new code.
authorTim Peters <tim.peters@gmail.com>
Sat, 8 Jan 2005 07:30:42 +0000 (07:30 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 8 Jan 2005 07:30:42 +0000 (07:30 +0000)
test_threading.test_foreign_thread():  new test does a basic check that
"foreign" threads can using the threading module, and that they create
a _DummyThread instance in at least one use case.  This isn't a very
good test, since a thread created by thread.start_new_thread() isn't
particularly "foreign".

Lib/test/test_threading.py
Lib/threading.py

index 8b17460f8abedaac4807a4b8acb6277dafbfc480..7eb9758ecf261fa5deb5a4ca51566115c3687563 100644 (file)
@@ -4,6 +4,7 @@ import test.test_support
 from test.test_support import verbose
 import random
 import threading
+import thread
 import time
 import unittest
 
@@ -78,11 +79,31 @@ class ThreadTests(unittest.TestCase):
         if verbose:
             print 'waiting for all tasks to complete'
         for t in threads:
-            t.join()
+            t.join(NUMTASKS)
+            self.assert_(not t.isAlive())
         if verbose:
             print 'all tasks done'
         self.assertEqual(numrunning.get(), 0)
 
+    def test_foreign_thread(self):
+        # Check that a "foreign" thread can use the threading module.
+        def f(mutex):
+            # Acquiring an RLock forces an entry for the foreign
+            # thread to get made in the threading._active map.
+            r = threading.RLock()
+            r.acquire()
+            r.release()
+            mutex.release()
+
+        mutex = threading.Lock()
+        mutex.acquire()
+        tid = thread.start_new_thread(f, (mutex,))
+        # Wait for the thread to finish.
+        mutex.acquire()
+        self.assert_(tid in threading._active)
+        self.assert_(isinstance(threading._active[tid],
+                                threading._DummyThread))
+        del threading._active[tid]
 
 def test_main():
     test.test_support.run_unittest(ThreadTests)
index 61c25b65344434e4da0fe3f36275c78eb56dfbd7..1aed551c5ff318b6e25d71f475d9d3063cc010fc 100644 (file)
@@ -358,7 +358,7 @@ def _newname(template="Thread-%d"):
 
 # Active thread administration
 _active_limbo_lock = _allocate_lock()
-_active = {}
+_active = {}    # maps thread id to Thread object
 _limbo = {}
 
 
@@ -643,8 +643,9 @@ def _pickSomeNonDaemonThread():
 
 
 # Dummy thread class to represent threads not started here.
-# These aren't garbage collected when they die,
-# nor can they be waited for.
+# These aren't garbage collected when they die, nor can they be waited for.
+# If they invoke anything in threading.py that calls currentThread(), they
+# leave an entry in the _active dict forever after.
 # Their purpose is to return *something* from currentThread().
 # They are marked as daemon threads so we won't wait for them
 # when we exit (conform previous semantics).
@@ -653,7 +654,12 @@ class _DummyThread(Thread):
 
     def __init__(self):
         Thread.__init__(self, name=_newname("Dummy-%d"))
+
+        # Thread.__block consumes an OS-level locking primitive, which
+        # can never be used by a _DummyThread.  Since a _DummyThread
+        # instance is immortal, that's bad, so release this resource.
         del self._Thread__block
+
         self._Thread__started = True
         _active_limbo_lock.acquire()
         _active[_get_ident()] = self