issue 8777
Add threading.Barrier
diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst
index 7c8f709..64aa14b 100644
--- a/Doc/library/threading.rst
+++ b/Doc/library/threading.rst
@@ -768,6 +768,110 @@
only work if the timer is still in its waiting stage.
+.. _barrier-objects
+
+Barrier Objects
+---------------
+
+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 :meth:`wait` method and will block
+until all of the threads have made the call.
+At this points, the threads are released simultanously.
+
+The barrier can be reused any number of times for the same number of threads.
+
+As an example, here is a simple way to synchronize a client and server thread::
+
+ b = Barrier(2, timeout=5)
+ server():
+ start_server()
+ b.wait()
+ while True:
+ connection = accept_connection()
+ process_server_connection(connection)
+
+ client():
+ b.wait()
+ while True:
+ connection = make_connection()
+ process_client_connection(connection)
+
+.. class:: Barrier(parties, action=None, timeout=None)
+
+ Create a barrier object for *parties* number of threads. An *action*,
+ when provided, is a callable to be called by one of the threads when
+ they are released. *timeout* is the default timeout value if none
+ is specified for the :meth:`wait` method.
+
+ .. method:: wait(timeout=None)
+
+ Pass the barrier. When all the threads party to the barrier have called
+ this function, they are all released simultaneously. If a *timeout*
+ is provided, is is used in preference to any that was supplied to the
+ class constructor.
+
+ The return value is an integer in the range 0 to *parties*-1, different
+ for each thrad. This can be used to select a thread to do some special
+ housekeeping, eg:
+
+ i = barrier.wait()
+ if i == 0:
+ # Only one thread needs to print this
+ print("passed the barrier")
+
+ If an *action* was
+ provided to the constructor, one of the threads will have called it
+ prior to being released. Should this call raise an error, the barrier
+ is put into the broken state.
+
+ If the call times out, the barrier is put into the broken state.
+
+ This method may raise a :class:`BrokenBarrierError` exception if the
+ barrier is broken or reset while a thread is waiting
+
+ .. method:: reset()
+
+ Return the barrier to the default, empty state. Any threads waiting on
+ it will receive the :class:`BrokenBarrierError` exception.
+
+ Note that using this function may can require some external
+ synchronization if there are other threads whose state is unknown.
+ If a barrier is broken it may be better to just leave it and create a
+ new one.
+
+ .. method:: abort()
+
+ Put the barrier into a broken state. This causes any active or future
+ calls to :meth:`wait` to fail with the :class:`BrokenBarrierError`.
+ Use this for example if one of the needs to abort, to avoid deadlocking
+ the application.
+
+ It may be preferable to simply create the barrier with a sensible
+ *timeout* value to automatically guard against one of the threads
+ going awry.
+
+ .. attribute:: parties
+
+ The number of threads required to pass the barrier.
+
+ .. attribute:: n_waiting
+
+ The number of threads currently waiting in the barrier.
+
+ .. attribute:: broken
+
+ A boolean that is ``True`` if the barrier is in the broken state.
+
+ .. versionadded:: 3.2
+
+.. class:: BrokenBarrierError(RuntimeError)
+
+ The exception raised when the :class:`Barrier` object is reset or broken.
+
+ .. versionadded:: 3.2
+
+
.. _with-locks:
Using locks, conditions, and semaphores in the :keyword:`with` statement