Merged revisions 61038,61042-61045,61047,61050,61053,61055-61056,61061-61062,61066,61068,61070,61083,61085,61092-61103 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r61098 | jeffrey.yasskin | 2008-02-28 05:45:36 +0100 (Thu, 28 Feb 2008) | 7 lines

  Move abc._Abstract into object by adding a new flag Py_TPFLAGS_IS_ABSTRACT,
  which forbids constructing types that have it set. The effect is to speed

    ./python.exe -m timeit -s 'import abc' -s 'class Foo(object): __metaclass__ = abc.ABCMeta' 'Foo()'

  up from 2.5us to 0.201us. This fixes issue 1762.
........
  r61099 | jeffrey.yasskin | 2008-02-28 06:53:18 +0100 (Thu, 28 Feb 2008) | 3 lines

  Speed test_socketserver up from 28.739s to 0.226s, simplify the logic, and make
  sure all tests run even if some fail.
........
  r61100 | jeffrey.yasskin | 2008-02-28 07:09:19 +0100 (Thu, 28 Feb 2008) | 21 lines

  Thread.start() used sleep(0.000001) to make sure it didn't return before the
  new thread had started. At least on my MacBook Pro, that wound up sleeping for
  a full 10ms (probably 1 jiffy). By using an Event instead, we can be absolutely
  certain that the thread has started, and return more quickly (217us).

  Before:
  $  ./python.exe -m timeit -s 'from threading import Thread'  't = Thread(); t.start(); t.join()'
  100 loops, best of 3: 10.3 msec per loop
  $  ./python.exe -m timeit -s 'from threading import Thread; t = Thread()'  't.isAlive()'
  1000000 loops, best of 3: 0.47 usec per loop

  After:
  $  ./python.exe -m timeit -s 'from threading import Thread'  't = Thread(); t.start(); t.join()'
  1000 loops, best of 3: 217 usec per loop
  $  ./python.exe -m timeit -s 'from threading import Thread; t = Thread()'  't.isAlive()'
  1000000 loops, best of 3: 0.86 usec per loop

  To be fair, the 10ms isn't CPU time, and other threads including the spawned
  one get to run during it. There are also some slightly more complicated ways to
  get back the .4us in isAlive() if we want.
........
  r61101 | raymond.hettinger | 2008-02-28 10:23:48 +0100 (Thu, 28 Feb 2008) | 1 line

  Add repeat keyword argument to itertools.product().
........
  r61102 | christian.heimes | 2008-02-28 12:18:49 +0100 (Thu, 28 Feb 2008) | 1 line

  The empty tuple is usually a singleton with a much higher refcnt than 1
........
diff --git a/Lib/threading.py b/Lib/threading.py
index c09ec6a..d010b80 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -403,7 +403,7 @@
         self._args = args
         self._kwargs = kwargs
         self._daemonic = self._set_daemon()
-        self._started = False
+        self._started = Event()
         self._stopped = False
         self._block = Condition(Lock())
         self._initialized = True
@@ -418,7 +418,7 @@
     def __repr__(self):
         assert self._initialized, "Thread.__init__() was not called"
         status = "initial"
-        if self._started:
+        if self._started.isSet():
             status = "started"
         if self._stopped:
             status = "stopped"
@@ -429,7 +429,8 @@
     def start(self):
         if not self._initialized:
             raise RuntimeError("thread.__init__() not called")
-        if self._started:
+
+        if self._started.isSet():
             raise RuntimeError("thread already started")
         if __debug__:
             self._note("%s.start(): starting thread", self)
@@ -437,8 +438,7 @@
         _limbo[self] = self
         _active_limbo_lock.release()
         _start_new_thread(self._bootstrap, ())
-        self._started = True
-        _sleep(0.000001)    # 1 usec, to let the thread run (Solaris hack)
+        self._started.wait()
 
     def run(self):
         try:
@@ -455,11 +455,11 @@
         # happen when a daemon thread wakes up at an unfortunate
         # moment, finds the world around it destroyed, and raises some
         # random exception *** while trying to report the exception in
-        # __bootstrap_inner() below ***.  Those random exceptions
+        # _bootstrap_inner() below ***.  Those random exceptions
         # don't help anybody, and they confuse users, so we suppress
         # them.  We suppress them only when it appears that the world
         # indeed has already been destroyed, so that exceptions in
-        # __bootstrap_inner() during normal business hours are properly
+        # _bootstrap_inner() during normal business hours are properly
         # reported.  Also, we only suppress them for daemonic threads;
         # if a non-daemonic encounters this, something else is wrong.
         try:
@@ -471,29 +471,29 @@
 
     def _bootstrap_inner(self):
         try:
-            self._started = True
+            self._started.set()
             _active_limbo_lock.acquire()
             _active[_get_ident()] = self
             del _limbo[self]
             _active_limbo_lock.release()
             if __debug__:
-                self._note("%s.__bootstrap(): thread started", self)
+                self._note("%s._bootstrap(): thread started", self)
 
             if _trace_hook:
-                self._note("%s.__bootstrap(): registering trace hook", self)
+                self._note("%s._bootstrap(): registering trace hook", self)
                 _sys.settrace(_trace_hook)
             if _profile_hook:
-                self._note("%s.__bootstrap(): registering profile hook", self)
+                self._note("%s._bootstrap(): registering profile hook", self)
                 _sys.setprofile(_profile_hook)
 
             try:
                 self.run()
             except SystemExit:
                 if __debug__:
-                    self._note("%s.__bootstrap(): raised SystemExit", self)
+                    self._note("%s._bootstrap(): raised SystemExit", self)
             except:
                 if __debug__:
-                    self._note("%s.__bootstrap(): unhandled exception", self)
+                    self._note("%s._bootstrap(): unhandled exception", self)
                 # If sys.stderr is no more (most likely from interpreter
                 # shutdown) use self._stderr.  Otherwise still use sys (as in
                 # _sys) in case sys.stderr was redefined since the creation of
@@ -526,7 +526,7 @@
                         del exc_type, exc_value, exc_tb
             else:
                 if __debug__:
-                    self._note("%s.__bootstrap(): normal return", self)
+                    self._note("%s._bootstrap(): normal return", self)
         finally:
             with _active_limbo_lock:
                 self._stop()
@@ -580,7 +580,7 @@
     def join(self, timeout=None):
         if not self._initialized:
             raise RuntimeError("Thread.__init__() not called")
-        if not self._started:
+        if not self._started.isSet():
             raise RuntimeError("cannot join thread before it is started")
         if self is currentThread():
             raise RuntimeError("cannot join current thread")
@@ -621,7 +621,7 @@
 
     def isAlive(self):
         assert self._initialized, "Thread.__init__() not called"
-        return self._started and not self._stopped
+        return self._started.isSet() and not self._stopped
 
     def isDaemon(self):
         assert self._initialized, "Thread.__init__() not called"
@@ -630,7 +630,7 @@
     def setDaemon(self, daemonic):
         if not self._initialized:
             raise RuntimeError("Thread.__init__() not called")
-        if self._started:
+        if self._started.isSet():
             raise RuntimeError("cannot set daemon status of active thread");
         self._daemonic = daemonic
 
@@ -672,7 +672,7 @@
 
     def __init__(self):
         Thread.__init__(self, name="MainThread")
-        self._started = True
+        self._started.set()
         _active_limbo_lock.acquire()
         _active[_get_ident()] = self
         _active_limbo_lock.release()
@@ -718,7 +718,8 @@
         # instance is immortal, that's bad, so release this resource.
         del self._block
 
-        self._started = True
+
+        self._started.set()
         _active_limbo_lock.acquire()
         _active[_get_ident()] = self
         _active_limbo_lock.release()