]> granicus.if.org Git - python/commitdiff
#10968: commit threading doc changes and corresponding whatsnew entry.
authorR David Murray <rdmurray@bitdance.com>
Sat, 6 Oct 2012 18:35:35 +0000 (14:35 -0400)
committerR David Murray <rdmurray@bitdance.com>
Sat, 6 Oct 2012 18:35:35 +0000 (14:35 -0400)
It is unfortunate that the '_' names were not kept as aliases, and that RLock
was not also converted to a class, but it is now too late to change either of
those things for 3.3.

Doc/library/multiprocessing.rst
Doc/library/threading.rst
Doc/whatsnew/3.3.rst
Misc/NEWS

index 616b7cd5565c4edfa531ca30202aa93b920ab208..6c29e3f1f7cb8b3b28cd4b5889346f7497ce65de 100644 (file)
@@ -916,7 +916,7 @@ object -- see :ref:`multiprocessing-managers`.
 
 .. class:: Condition([lock])
 
-   A condition variable: a clone of :class:`threading.Condition`.
+   A condition variable: an alias for :class:`threading.Condition`.
 
    If *lock* is specified then it should be a :class:`Lock` or :class:`RLock`
    object from :mod:`multiprocessing`.
index 7ab739b507936fe50174e8f7d86c1a333475e1db..05863a0e731400af46ee794487619574e78a7ee4 100644 (file)
@@ -21,7 +21,7 @@ The :mod:`dummy_threading` module is provided for situations where
    supported by this module.
 
 
-This module defines the following functions and objects:
+This module defines the following functions:
 
 
 .. function:: active_count()
@@ -30,16 +30,6 @@ This module defines the following functions and objects:
    count is equal to the length of the list returned by :func:`.enumerate`.
 
 
-.. function:: Condition()
-   :noindex:
-
-   A factory function that returns a new condition variable object. A condition
-   variable allows one or more threads to wait until they are notified by another
-   thread.
-
-   See :ref:`condition-objects`.
-
-
 .. function:: current_thread()
 
    Return the current :class:`Thread` object, corresponding to the caller's thread
@@ -67,88 +57,6 @@ This module defines the following functions and objects:
    and threads that have not yet been started.
 
 
-.. function:: Event()
-   :noindex:
-
-   A factory function that returns a new event object.  An event manages a flag
-   that can be set to true with the :meth:`~Event.set` method and reset to false
-   with the :meth:`clear` method.  The :meth:`wait` method blocks until the flag
-   is true.
-
-   See :ref:`event-objects`.
-
-
-.. class:: local
-
-   A class that represents thread-local data.  Thread-local data are data whose
-   values are thread specific.  To manage thread-local data, just create an
-   instance of :class:`local` (or a subclass) and store attributes on it::
-
-      mydata = threading.local()
-      mydata.x = 1
-
-   The instance's values will be different for separate threads.
-
-   For more details and extensive examples, see the documentation string of the
-   :mod:`_threading_local` module.
-
-
-.. function:: Lock()
-
-   A factory function that returns a new primitive lock object.  Once a thread has
-   acquired it, subsequent attempts to acquire it block, until it is released; any
-   thread may release it.
-
-   See :ref:`lock-objects`.
-
-
-.. function:: RLock()
-
-   A factory function that returns a new reentrant lock object. A reentrant lock
-   must be released by the thread that acquired it. Once a thread has acquired a
-   reentrant lock, the same thread may acquire it again without blocking; the
-   thread must release it once for each time it has acquired it.
-
-   See :ref:`rlock-objects`.
-
-
-.. function:: Semaphore(value=1)
-   :noindex:
-
-   A factory function that returns a new semaphore object.  A semaphore manages a
-   counter representing the number of :meth:`release` calls minus the number of
-   :meth:`acquire` calls, plus an initial value. The :meth:`acquire` method blocks
-   if necessary until it can return without making the counter negative.  If not
-   given, *value* defaults to 1.
-
-   See :ref:`semaphore-objects`.
-
-
-.. function:: BoundedSemaphore(value=1)
-
-   A factory function that returns a new bounded semaphore object.  A bounded
-   semaphore checks to make sure its current value doesn't exceed its initial
-   value.  If it does, :exc:`ValueError` is raised. In most situations semaphores
-   are used to guard resources with limited capacity.  If the semaphore is released
-   too many times it's a sign of a bug.  If not given, *value* defaults to 1.
-
-
-.. class:: Thread
-
-   A class that represents a thread of control.  This class can be safely
-   subclassed in a limited fashion.
-
-   See :ref:`thread-objects`.
-
-
-.. class:: Timer
-   :noindex:
-
-   A thread that executes a function after a specified interval has passed.
-
-   See :ref:`timer-objects`.
-
-
 .. function:: settrace(func)
 
    .. index:: single: trace function
@@ -197,7 +105,8 @@ This module also defines the following constant:
    .. versionadded:: 3.2
 
 
-Detailed interfaces for the objects are documented below.
+This module defines a number of classes, which are detailed in the sections
+below.
 
 The design of this module is loosely based on Java's threading model. However,
 where Java makes locks and condition variables basic behavior of every object,
@@ -210,17 +119,38 @@ when implemented, are mapped to module-level functions.
 All of the methods described below are executed atomically.
 
 
+Thread-Local Data
+-----------------
+
+Thread-local data is data whose values are thread specific.  To manage
+thread-local data, just create an instance of :class:`local` (or a
+subclass) and store attributes on it::
+
+  mydata = threading.local()
+  mydata.x = 1
+
+The instance's values will be different for separate threads.
+
+
+.. class:: local()
+
+   A class that represents thread-local data.
+
+   For more details and extensive examples, see the documentation string of the
+   :mod:`_threading_local` module.
+
+
 .. _thread-objects:
 
 Thread Objects
 --------------
 
-This class represents an activity that is run in a separate thread of control.
-There are two ways to specify the activity: by passing a callable object to the
-constructor, or by overriding the :meth:`~Thread.run` method in a subclass.
-No other methods (except for the constructor) should be overridden in a
-subclass.  In other words,  *only*  override the :meth:`~Thread.__init__`
-and :meth:`~Thread.run` methods of this class.
+The :class:`Thread` class represents an activity that is run in a separate
+thread of control.  There are two ways to specify the activity: by passing a
+callable object to the constructor, or by overriding the :meth:`~Thread.run`
+method in a subclass.  No other methods (except for the constructor) should be
+overridden in a subclass.  In other words, *only*  override the
+:meth:`~Thread.__init__` and :meth:`~Thread.run` methods of this class.
 
 Once a thread object is created, its activity must be started by calling the
 thread's :meth:`~Thread.start` method.  This invokes the :meth:`~Thread.run`
@@ -419,45 +349,55 @@ is not defined, and may vary across implementations.
 All methods are executed atomically.
 
 
-.. method:: Lock.acquire(blocking=True, timeout=-1)
+.. class:: Lock()
 
-   Acquire a lock, blocking or non-blocking.
+   The class implementing primitive lock objects.  Once a thread has acquired a
+   lock, subsequent attempts to acquire it block, until it is released; any
+   thread may release it.
 
-   When invoked with the *blocking* argument set to ``True`` (the default),
-   block until the lock is unlocked, then set it to locked and return ``True``.
+   .. versionchanged:: 3.3
+      Changed from a factory function to a class.
 
-   When invoked with the *blocking* argument set to ``False``, do not block.
-   If a call with *blocking* set to ``True`` would block, return ``False``
-   immediately; otherwise, set the lock to locked and return ``True``.
 
-   When invoked with the floating-point *timeout* argument set to a positive
-   value, block for at most the number of seconds specified by *timeout*
-   and as long as the lock cannot be acquired.  A negative *timeout* argument
-   specifies an unbounded wait.  It is forbidden to specify a *timeout*
-   when *blocking* is false.
+   .. method:: acquire(blocking=True, timeout=-1)
 
-   The return value is ``True`` if the lock is acquired successfully,
-   ``False`` if not (for example if the *timeout* expired).
+      Acquire a lock, blocking or non-blocking.
 
-   .. versionchanged:: 3.2
-      The *timeout* parameter is new.
+      When invoked with the *blocking* argument set to ``True`` (the default),
+      block until the lock is unlocked, then set it to locked and return ``True``.
 
-   .. versionchanged:: 3.2
-      Lock acquires can now be interrupted by signals on POSIX.
+      When invoked with the *blocking* argument set to ``False``, do not block.
+      If a call with *blocking* set to ``True`` would block, return ``False``
+      immediately; otherwise, set the lock to locked and return ``True``.
 
+      When invoked with the floating-point *timeout* argument set to a positive
+      value, block for at most the number of seconds specified by *timeout*
+      and as long as the lock cannot be acquired.  A negative *timeout* argument
+      specifies an unbounded wait.  It is forbidden to specify a *timeout*
+      when *blocking* is false.
 
-.. method:: Lock.release()
+      The return value is ``True`` if the lock is acquired successfully,
+      ``False`` if not (for example if the *timeout* expired).
 
-   Release a lock.  This can be called from any thread, not only the thread
-   which has acquired the lock.
+      .. versionchanged:: 3.2
+         The *timeout* parameter is new.
 
-   When the lock is locked, reset it to unlocked, and return.  If any other threads
-   are blocked waiting for the lock to become unlocked, allow exactly one of them
-   to proceed.
+      .. versionchanged:: 3.2
+         Lock acquires can now be interrupted by signals on POSIX.
+
+
+   .. method:: release()
+
+      Release a lock.  This can be called from any thread, not only the thread
+      which has acquired the lock.
+
+      When the lock is locked, reset it to unlocked, and return.  If any other threads
+      are blocked waiting for the lock to become unlocked, allow exactly one of them
+      to proceed.
 
-   When invoked on an unlocked lock, a :exc:`RuntimeError` is raised.
+      When invoked on an unlocked lock, a :exc:`RuntimeError` is raised.
 
-   There is no return value.
+      There is no return value.
 
 
 .. _rlock-objects:
@@ -481,47 +421,59 @@ allows another thread blocked in :meth:`~Lock.acquire` to proceed.
 Reentrant locks also support the :ref:`context manager protocol <with-locks>`.
 
 
-.. method:: RLock.acquire(blocking=True, timeout=-1)
+.. class:: RLock()
 
-   Acquire a lock, blocking or non-blocking.
+   This class implements reentrant lock objects.  A reentrant lock must be
+   released by the thread that acquired it.  Once a thread has acquired a
+   reentrant lock, the same thread may acquire it again without blocking; the
+   thread must release it once for each time it has acquired it.
 
-   When invoked without arguments: if this thread already owns the lock, increment
-   the recursion level by one, and return immediately.  Otherwise, if another
-   thread owns the lock, block until the lock is unlocked.  Once the lock is
-   unlocked (not owned by any thread), then grab ownership, set the recursion level
-   to one, and return.  If more than one thread is blocked waiting until the lock
-   is unlocked, only one at a time will be able to grab ownership of the lock.
-   There is no return value in this case.
+   Note that ``RLock`` is actually a factory function which returns an instance
+   of the most efficient version of the concrete RLock class that is supported
+   by the platform.
 
-   When invoked with the *blocking* argument set to true, do the same thing as when
-   called without arguments, and return true.
 
-   When invoked with the *blocking* argument 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.
+   .. method:: acquire(blocking=True, timeout=-1)
 
-   When invoked with the floating-point *timeout* argument set to a positive
-   value, block for at most the number of seconds specified by *timeout*
-   and as long as the lock cannot be acquired.  Return true if the lock has
-   been acquired, false if the timeout has elapsed.
+      Acquire a lock, blocking or non-blocking.
 
-   .. versionchanged:: 3.2
-      The *timeout* parameter is new.
+      When invoked without arguments: if this thread already owns the lock, increment
+      the recursion level by one, and return immediately.  Otherwise, if another
+      thread owns the lock, block until the lock is unlocked.  Once the lock is
+      unlocked (not owned by any thread), then grab ownership, set the recursion level
+      to one, and return.  If more than one thread is blocked waiting until the lock
+      is unlocked, only one at a time will be able to grab ownership of the lock.
+      There is no return value in this case.
 
+      When invoked with the *blocking* argument set to true, do the same thing as when
+      called without arguments, and return true.
 
-.. method:: RLock.release()
+      When invoked with the *blocking* argument 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.
 
-   Release a 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.
+      When invoked with the floating-point *timeout* argument set to a positive
+      value, block for at most the number of seconds specified by *timeout*
+      and as long as the lock cannot be acquired.  Return true if the lock has
+      been acquired, false if the timeout has elapsed.
 
-   Only call this method when the calling thread owns the lock. A
-   :exc:`RuntimeError` is raised if this method is called when the lock is
-   unlocked.
+      .. versionchanged:: 3.2
+         The *timeout* parameter is new.
 
-   There is no return value.
+
+   .. method:: release()
+
+      Release a 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.
+
+      Only call this method when the calling thread owns the lock. A
+      :exc:`RuntimeError` is raised if this method is called when the lock is
+      unlocked.
+
+      There is no return value.
 
 
 .. _condition-objects:
@@ -556,10 +508,6 @@ not return from their :meth:`~Condition.wait` call immediately, but only when
 the thread that called :meth:`~Condition.notify` or :meth:`~Condition.notify_all`
 finally relinquishes ownership of the lock.
 
-
-Usage
-^^^^^
-
 The typical programming style using condition variables uses the lock to
 synchronize access to some shared state; threads that are interested in a
 particular change of state call :meth:`~Condition.wait` repeatedly until they
@@ -598,15 +546,18 @@ waiting threads.  E.g. in a typical producer-consumer situation, adding one
 item to the buffer only needs to wake up one consumer thread.
 
 
-Interface
-^^^^^^^^^
-
 .. class:: Condition(lock=None)
 
+   This class implements condition variable objects.  A condition variable
+   allows one or more threads to wait until they are notified by another thread.
+
    If the *lock* argument is given and not ``None``, it must be a :class:`Lock`
    or :class:`RLock` object, and it is used as the underlying lock.  Otherwise,
    a new :class:`RLock` object is created and used as the underlying lock.
 
+   .. versionchanged:: 3.3
+      changed from a factory function to a class.
+
    .. method:: acquire(*args)
 
       Acquire the underlying lock. This method calls the corresponding method on
@@ -716,10 +667,19 @@ Semaphores also support the :ref:`context manager protocol <with-locks>`.
 
 .. class:: Semaphore(value=1)
 
+   This class implements semaphore objects.  A semaphore manages a counter
+   representing the number of :meth:`release` calls minus the number of
+   :meth:`acquire` calls, plus an initial value.  The :meth:`acquire` method
+   blocks if necessary until it can return without making the counter negative.
+   If not given, *value* defaults to 1.
+
    The optional argument gives the initial *value* for the internal counter; it
    defaults to ``1``. If the *value* given is less than 0, :exc:`ValueError` is
    raised.
 
+   .. versionchanged:: 3.3
+      changed from a factory function to a class.
+
    .. method:: acquire(blocking=True, timeout=None)
 
       Acquire a semaphore.
@@ -752,6 +712,18 @@ Semaphores also support the :ref:`context manager protocol <with-locks>`.
       than zero again, wake up that thread.
 
 
+.. class:: BoundedSemaphore(value=1)
+
+   Class implementing bounded semaphore objects.  A bounded semaphore checks to
+   make sure its current value doesn't exceed its initial value.  If it does,
+   :exc:`ValueError` is raised. In most situations semaphores are used to guard
+   resources with limited capacity.  If the semaphore is released too many times
+   it's a sign of a bug.  If not given, *value* defaults to 1.
+
+   .. versionchanged:: 3.3
+      changed from a factory function to a class.
+
+
 .. _semaphore-examples:
 
 :class:`Semaphore` Example
@@ -763,7 +735,7 @@ you should use a bounded semaphore.  Before spawning any worker threads, your
 main thread would initialize the semaphore::
 
    maxconnections = 5
-   ...
+   ...
    pool_sema = BoundedSemaphore(value=maxconnections)
 
 Once spawned, worker threads call the semaphore's acquire and release methods
@@ -772,7 +744,7 @@ when they need to connect to the server::
    with pool_sema:
        conn = connectdb()
        try:
-           ... use connection ...
+           ... use connection ...
        finally:
            conn.close()
 
@@ -795,7 +767,13 @@ method.  The :meth:`~Event.wait` method blocks until the flag is true.
 
 .. class:: Event()
 
-   The internal flag is initially false.
+   Class implementing event objects.  An event manages a flag that can be set to
+   true with the :meth:`~Event.set` method and reset to false with the
+   :meth:`clear` method.  The :meth:`wait` method blocks until the flag is true.
+   The flag is initially false.
+
+   .. versionchanged:: 3.3
+      changed from a factory function to a class.
 
    .. method:: is_set()
 
@@ -860,6 +838,9 @@ For example::
    Create a timer that will run *function* with arguments *args* and  keyword
    arguments *kwargs*, after *interval* seconds have passed.
 
+   .. versionchanged:: 3.3
+      changed from a factory function to a class.
+
    .. method:: cancel()
 
       Stop the timer, and cancel the execution of the timer's action.  This will
index 088ea4a0defd55605e41e0390a059f0e30e74ee0..1fef8d3cbe98ca57735e2dc22a4e9584e89abb62 100644 (file)
@@ -1945,6 +1945,12 @@ of text  (:issue:`13857`).
 threading
 ---------
 
+:class:`threading.Condition`, :class:`threading.Semaphore`,
+:class:`threading.BoundedSempaphore`, :class:`threading.Event`, and
+:class:`threading.Timer`, all of which used to be factory functions returning a
+class instance, are now classes and may be subclassed. (Contributed by Éric
+Araujo in :issue:`109681`).
+
 The :class:`threading.Thread` constructor now accepts a ``daemon`` keyword
 argument to override the default behavior of inheriting the ``deamon`` flag
 value from the parent thread (:issue:`6064`).
@@ -2331,6 +2337,10 @@ Porting Python code
   make decisions affected by the AST version, use :attr:`sys.version_info`
   to make the decision.
 
+* Code that used to work around the fact that the :mod:`threading` module used
+  factory functions by subclassing the private classes will need to change to
+  subclass the now-public classes.
+
 
 Porting C code
 --------------
index 74c2004fb5cda7a9852ce30c0922e4c2735f5d04..be761e6cb8661dd0e8385ef40c4facf3c2c2d9f8 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -3031,11 +3031,11 @@ Library
 - Issue #8887: "pydoc somebuiltin.somemethod" (or help('somebuiltin.somemethod')
   in Python code) now finds the doc of the method.
 
-- Issue #10968: Remove indirection in threading.  The public names (Thread,
+- Issue #10968: Remove indirection in threading.  The public names (Event,
   Condition, etc.) used to be factory functions returning instances of hidden
-  classes (_Thread, _Condition, etc.), because (if Guido recalls correctly) this
-  code pre-dates the ability to subclass extension types.  It is now possible to
-  inherit from Thread and other classes, without having to import the private
+  classes (_Event, _Condition, etc.), because (if Guido recalls correctly) this
+  code pre-dates the ability to subclass extension types.  It is now possible
+  to inherit from these classes, without having to import the private
   underscored names like multiprocessing did.
 
 - Issue #9723: Add shlex.quote functions, to escape filenames and command