diff -r 4f9de1b18cab Lib/threading.py --- a/Lib/threading.py Wed Mar 06 03:20:27 2013 +0200 +++ b/Lib/threading.py Wed Mar 06 07:39:17 2013 -0800 @@ -1,4 +1,7 @@ -"""Thread module emulating a subset of Java's threading model.""" +"""Thread module emulating a subset of Java's threading model for thread-based + +parallelism. +""" import sys as _sys import _thread @@ -8,11 +11,11 @@ from _weakrefset import WeakSet # Note regarding PEP 8 compliant names -# This threading model was originally inspired by Java, and inherited +# This threading model was originally inspired by Java, and inherited # the convention of camelCase function and method names from that -# language. Those originaly names are not in any imminent danger of -# being deprecated (even for Py3k),so this module provides them as an -# alias for the PEP 8 compliant names +# language. These originaly names are not in any imminent danger of +# being deprecated (even for Py3k), so this module provides them as an +# alias for the PEP 8 compliant names. # Note that using the new PEP 8 compliant names facilitates substitution # with the multiprocessing module, which doesn't provide the old # Java inspired names. @@ -86,6 +89,13 @@ Lock = _allocate_lock def RLock(verbose=None, *args, **kwargs): + """ + A reentrant lock is a synchronization primitive that may be acquired + multiple times by the same thread. Internally, it uses the concepts of + "owning thread" and "recursion level" in addition to the locked/unlocked + state used by primitive locks. In the locked state, some thread owns the + lock; in the unlocked state, no thread owns it. + """ if verbose is None: verbose = _VERBOSE if (__debug__ and verbose) or _CRLock is None: @@ -110,6 +120,10 @@ self.__class__.__name__, owner, self._count) def acquire(self, blocking=True, timeout=-1): + """ + Acquire this lock, blocking or non-blocking, with an optional timeout + (in seconds). + """ me = _get_ident() if self._owner == me: self._count = self._count + 1 @@ -130,6 +144,14 @@ __enter__ = acquire def release(self): + """ + Release this lock, decrementing the recursion level. If after the + decrement it is zero, reset the lock to unlocked (not owned by any + thread), and if any other threads are blocked waiting for the lock to + become unlocked, allow exactly one of them to proceed. If after the + decrement the recursion level is still nonzero, the lock remains + locked and owned by the calling thread. + """ if self._owner != _get_ident(): raise RuntimeError("cannot release un-acquired lock") self._count = count = self._count - 1 @@ -173,6 +195,10 @@ return _Condition(*args, **kwargs) class _Condition(_Verbose): + """ + A condition variable that allows one or more threads to wait until they + are notified by another thread. A Condition may be created with a lock. + """ def __init__(self, lock=None, verbose=None): _Verbose.__init__(self, verbose) @@ -224,6 +250,11 @@ return True def wait(self, timeout=None): + """ + Wait until notified or until an optional timeout (in seconds) has + occured. If the calling thread has not acquired the lock when this + method is called, a RunTimeError is raised. + """ if not self._is_owned(): raise RuntimeError("cannot wait on un-acquired lock") waiter = _allocate_lock() @@ -256,6 +287,16 @@ self._acquire_restore(saved_state) def wait_for(self, predicate, timeout=None): + """ + Wait until a condition evaluates to True. 'predicate' should be a + callable, the result of which will be interpreted as a boolean value. + An optional timeout (in seconds) may be provided giving the maximum + time to wait. + This utility method may call wait() repeatedly until the predicate is + satisfied, or until a timeout occurs. The return value is the last + return value of the predicate and will evaluate to False if the method + timed out. + """ endtime = None waittime = timeout result = predicate() @@ -282,6 +323,13 @@ return result def notify(self, n=1): + """ + Wake up one or more threads waiting on this condition. The parameter n + , defaulting to 1, specifies the number of threads to release; the + first n threads in the list of waiting threads are released. + If the calling thread has not acquired the lock when this method is + called, a RunTimeError is raised. + """ if not self._is_owned(): raise RuntimeError("cannot notify on un-acquired lock") __waiters = self._waiters @@ -300,6 +348,12 @@ pass def notify_all(self): + """ + Wake up all threads waiting on this condition. This method acts like + notify(), but wakes up all waiting threads instead of one. If the + calling thread has not acquired the lock when this method is called, a + RunTimeError is raised. + """ self.notify(len(self._waiters)) notifyAll = notify_all @@ -309,7 +363,14 @@ return _Semaphore(*args, **kwargs) class _Semaphore(_Verbose): - + """ + A semaphore is a synchronization mechanism that manages an internal counter + which is decremented by a call to acquire() and incremented by a call to + release(). The counter can never go below 0; when acquire() finds that it + is 0, it blocks, waiting until some other thread calls release(). The + counter is initialized to default value 1. A ValueError is raised if the + value of counter is set to a value less than 0. + """ # After Tim Peters' semaphore class, but not quite the same (no maximum) def __init__(self, value=1, verbose=None): @@ -320,6 +381,15 @@ self._value = value def acquire(self, blocking=True, timeout=None): + """ + Acquire a semaphore. + When invoked with blocking set to False, do not block. If a call without + an argument would block, return False immediately; otherwise, do the + same thing as when called without arguments, and return True. + When invoked with a timeout other than None, it will block for at most + timeout seconds. If acquire does not complete successfully in that + interval, return False. Return True otherwise. + """ if not blocking and timeout is not None: raise ValueError("can't specify timeout for non-blocking acquire") rc = False @@ -351,6 +421,11 @@ __enter__ = acquire def release(self): + """ + Release a semaphore incrementing the internal counter by one. If it is + 0 on entry and another thread is waiting for it to become greater than + 0 again, notify that thread. + """ self._cond.acquire() self._value = self._value + 1 if __debug__: @@ -367,12 +442,20 @@ return _BoundedSemaphore(*args, **kwargs) class _BoundedSemaphore(_Semaphore): - """Semaphore that checks that # releases is <= # acquires""" + """ + A bounded semaphore is a semaphore that ensures that the counter value + does not exceed its initial value raising a ValueError if it does. + """ + def __init__(self, value=1, verbose=None): _Semaphore.__init__(self, value, verbose) self._initial_value = value def release(self): + """ + Release the semaphore; raise ValueError if the value of the counter is + greater than its initial value. + """ if self._value >= self._initial_value: raise ValueError("Semaphore released too many times") return _Semaphore.release(self) @@ -382,7 +465,11 @@ return _Event(*args, **kwargs) class _Event(_Verbose): - + """ + An Event manages a flag that can be set to True/False, the default being + False, with the set() method and reset reset to False with the clear() + method. The wait() method blocks until the flag is True. + """ # After Tim Peters' event class (without is_posted()) def __init__(self, verbose=None): @@ -395,11 +482,17 @@ self._cond.__init__() def is_set(self): + """Return True if and only if the internal flag is True.""" return self._flag isSet = is_set def set(self): + """ + Set the internal flag to True. All threads waiting for it to become + True are awakened. Threads that call wait() once the flag is True will + not block at all. + """ self._cond.acquire() try: self._flag = True @@ -408,6 +501,10 @@ self._cond.release() def clear(self): + """ + Reset the internal flag to False. Subsequently, threads calling wait() + will block until the flag is set to True. + """ self._cond.acquire() try: self._flag = False @@ -415,6 +512,16 @@ self._cond.release() def wait(self, timeout=None): + """ + Block until the internal flag is True. If the internal flag is True on + entry, return immediately. Otherwise, block until another thread calls + set() to set the flag to True, or until the optional timeout occurs. + When the timeout argument is present and not None, it should be a + floating point number specifying a timeout for the operation in seconds + (or a fraction thereof). + This method returns the internal flag on exit, so it will always return + True except if a timeout is given and the operation times out. + """ self._cond.acquire() try: signaled = self._flag @@ -438,18 +545,22 @@ # and a 'broken' state in which all threads get the exception. class Barrier(_Verbose): """ - Barrier. Useful for synchronizing a fixed number of threads - at known synchronization points. Threads block on 'wait()' and are - simultaneously once they have all made that call. + This class provides a simple synchronization primitive for use by a fixed + number of threads that need to wait for each other. Each of the threads + tries to pass the barrier by calling the wait() method and will block until + all of the threads have made the call. At this points, the threads are + released simultaneously. + The barrier can be reused any number of times for the same number of + threads. """ def __init__(self, parties, action=None, timeout=None, verbose=None): """ Create a barrier, initialised to 'parties' threads. - 'action' is a callable which, when supplied, will be called - by one of the threads after they have all entered the - barrier and just prior to releasing them all. - If a 'timeout' is provided, it is uses as the default for - all subsequent 'wait()' calls. + 'action' is a callable which, when supplied, will be called by one of + the threads after they have all entered the barrier and just prior to + releasing them all. + If a 'timeout' is provided, it is uses as the default for all subsequent + 'wait()' calls. """ _Verbose.__init__(self, verbose) self._cond = Condition(Lock()) @@ -461,10 +572,10 @@ def wait(self, timeout=None): """ - Wait for the barrier. When the specified number of threads have - started waiting, they are all simultaneously awoken. If an 'action' - was provided for the barrier, one of the threads will have executed - that callback prior to returning. + Wait for the barrier, with an optional timeout (in seconds). When the + specified number of threads have started waiting, they are all + simultaneously awoken. If an 'action' was provided for the barrier, one + of the threads will have executed that callback prior to returning. Returns an individual index number from 0 to 'parties-1'. """ if timeout is None: @@ -533,9 +644,8 @@ def reset(self): """ - Reset the barrier to the initial state. - Any threads currently waiting will get the BrokenBarrier exception - raised. + Reset the barrier to the initial state. Any threads currently waiting + will get the BrokenBarrier exception raised. """ with self._cond: if self._count > 0: @@ -568,9 +678,7 @@ @property def parties(self): - """ - Return the number of threads required to trip the barrier. - """ + """Return the number of threads required to trip the barrier.""" return self._parties @property @@ -586,13 +694,13 @@ @property def broken(self): - """ - Return True if the barrier is in a broken state - """ + """Return True if the barrier is in a broken state.""" return self._state == -2 #exception raised by the Barrier class -class BrokenBarrierError(RuntimeError): pass +class BrokenBarrierError(RuntimeError): + """Exception raised by the Barrier class.""" + pass # Helper to generate new thread names @@ -613,7 +721,10 @@ # Main class for threads class Thread(_Verbose): - + """ + A class that represents a threas of control. This class can be safely + subclassed in a limited fashion. + """ __initialized = False # Need to store a reference to sys.exc_info for printing # out exceptions when a thread tries to use a global var. during interp. @@ -626,6 +737,32 @@ def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None): + """ + This constructor should always be called with keyword arguments. + Arguments are: + + 'group' should be None; reserved for future extension when a ThreadGroup + class is implemented. + + 'target' is the callable object to be invoked by the run() method. + Defaults to None, meaning nothing is called. + + 'name' is the thread name. By default, a unique name is constructed of + the form "Thread-N" where N is a small decimal number. + + 'args' is the argument tuple for the target invocation. Defaults to (). + + 'kwargs' is a dictionary of keyword arguments for the target invocation. + Defaults to {}. + + 'verbose' is a flag used for debugging messages. + + 'daemon' explicitly sets the thread's daemonic property if it is not + None. + + If None (the default), the daemonic property is inherited from the + current thread. + """ assert group is None, "group argument must be None for now" _Verbose.__init__(self, verbose) if kwargs is None: @@ -670,6 +807,13 @@ return "<%s(%s, %s)>" % (self.__class__.__name__, self._name, status) def start(self): + """ + Start the thread's activity. + It must be called at most once per thread object. It arranges for the + object's run() method to be invoked in a separate thread of control. + This method will raise a RuntimeError if called more than once on the + same thread object. + """ if not self._initialized: raise RuntimeError("thread.__init__() not called") @@ -688,6 +832,13 @@ self._started.wait() def run(self): + """ + Method representing the thread's activity. + You may override this method in a subclass. The standard run() method + invokes the callable object passed to the object's constructor as the + target argument, if any, with sequential and keyword arguments taken + from the args and kwargs arguments, respectively. + """ try: if self._target: self._target(*self._args, **self._kwargs) @@ -836,6 +987,12 @@ raise def join(self, timeout=None): + """ + Wait until the thread terminates. This blocks the calling thread until + the thread whose join() method is called terminates -- either normally + or through an unhandled exception -- or until the optional timeout + occurs. + """ if not self._initialized: raise RuntimeError("Thread.__init__() not called") if not self._started.is_set(): @@ -871,6 +1028,11 @@ @property def name(self): + """ + A string used for identification purposes only. It has no semantics. + Multiple threads may be given the same name. The initial name is set by + the constructor. + """ assert self._initialized, "Thread.__init__() not called" return self._name @@ -881,10 +1043,22 @@ @property def ident(self): + """ + Returns the 'thread identifier' of this thread or None if the thread has + not been started. This is a nonzero integer. See the get_ident() + function. Thread identifiers may be recycled when a thread exits and + another thread is created. The identifier is available even after the + thread has exited. + """ assert self._initialized, "Thread.__init__() not called" return self._ident def is_alive(self): + """ + Return whether the thread is alive. + This method returns True just before the run() method starts until just + after the run() method terminates. + """ assert self._initialized, "Thread.__init__() not called" return self._started.is_set() and not self._stopped @@ -892,6 +1066,11 @@ @property def daemon(self): + """ + A boolean value indicating whether this thread is a daemon thread (True) + or not (False). This must be set before start() is called, otherwise + RuntimeError is raised. + """ assert self._initialized, "Thread.__init__() not called" return self._daemonic @@ -921,7 +1100,9 @@ return _Timer(*args, **kwargs) class _Timer(Thread): - """Call a function after a specified number of seconds: + """ + A thread that executes a function after a specified number of seconds have + passed: t = Timer(30.0, f, args=[], kwargs={}) t.start() @@ -929,6 +1110,10 @@ """ def __init__(self, interval, function, args=[], kwargs={}): + """ + Create a timer that will run function with arguments 'args' and keyword + arguments 'kwargs', after 'interval' seconds have passed. + """ Thread.__init__(self) self.interval = interval self.function = function @@ -937,7 +1122,10 @@ self.finished = Event() def cancel(self): - """Stop the timer if it hasn't finished yet""" + """ + Stop the timer, and cancel the execution of the timer's action. This + will only work if the timer is still in its waiting stage. + """ self.finished.set() def run(self): @@ -1017,6 +1205,12 @@ # Global API functions def current_thread(): + """ + Return the current Thread object, corresponding to the caller's thread of + control. If the caller's thread of control was not created through the + threading module, a dummy thread object with limited functionality is + returned. + """ try: return _active[_get_ident()] except KeyError: @@ -1026,6 +1220,10 @@ currentThread = current_thread def active_count(): + """ + Return the number of Thread objects currently alive. The returned count is + equal to the length of the list returned by enumerate(). + """ with _active_limbo_lock: return len(_active) + len(_limbo) @@ -1036,6 +1234,12 @@ return list(_active.values()) + list(_limbo.values()) def enumerate(): + """ + Return a list of all Thread objects currently alive. The list includes + daemonic threads, dummy thread objects created by current_thread(), and the + main thread. It excludes terminated threads and threads that have not yet + been started. + """ with _active_limbo_lock: return list(_active.values()) + list(_limbo.values()) diff -r 4f9de1b18cab Misc/ACKS --- a/Misc/ACKS Wed Mar 06 03:20:27 2013 +0200 +++ b/Misc/ACKS Wed Mar 06 07:39:17 2013 -0800 @@ -233,6 +233,7 @@ Christopher A. Craig Jeremy Craven Laura Creighton +Graeme Cross Simon Cross Felipe Cruz Drew Csillag