mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-43352: Add a Barrier object in asyncio lib (GH-24903)
Co-authored-by: Yury Selivanov <yury@edgedb.com> Co-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>
This commit is contained in:
parent
20e6e5636a
commit
d03acd7270
6 changed files with 856 additions and 5 deletions
|
@ -28,6 +28,7 @@ asyncio has the following basic synchronization primitives:
|
|||
* :class:`Condition`
|
||||
* :class:`Semaphore`
|
||||
* :class:`BoundedSemaphore`
|
||||
* :class:`Barrier`
|
||||
|
||||
|
||||
---------
|
||||
|
@ -340,6 +341,115 @@ BoundedSemaphore
|
|||
.. versionchanged:: 3.10
|
||||
Removed the *loop* parameter.
|
||||
|
||||
|
||||
Barrier
|
||||
=======
|
||||
|
||||
.. class:: Barrier(parties, action=None)
|
||||
|
||||
A barrier object. Not thread-safe.
|
||||
|
||||
A barrier is a simple synchronization primitive that allows to block until
|
||||
*parties* number of tasks are waiting on it.
|
||||
Tasks can wait on the :meth:`~Barrier.wait` method and would be blocked until
|
||||
the specified number of tasks end up waiting on :meth:`~Barrier.wait`.
|
||||
At that point all of the waiting tasks would unblock simultaneously.
|
||||
|
||||
:keyword:`async with` can be used as an alternative to awaiting on
|
||||
:meth:`~Barrier.wait`.
|
||||
|
||||
The barrier can be reused any number of times.
|
||||
|
||||
.. _asyncio_example_barrier:
|
||||
|
||||
Example::
|
||||
|
||||
async def example_barrier():
|
||||
# barrier with 3 parties
|
||||
b = asyncio.Barrier(3)
|
||||
|
||||
# create 2 new waiting tasks
|
||||
asyncio.create_task(b.wait())
|
||||
asyncio.create_task(b.wait())
|
||||
|
||||
await asyncio.sleep(0)
|
||||
print(b)
|
||||
|
||||
# The third .wait() call passes the barrier
|
||||
await b.wait()
|
||||
print(b)
|
||||
print("barrier passed")
|
||||
|
||||
await asyncio.sleep(0)
|
||||
print(b)
|
||||
|
||||
asyncio.run(example_barrier())
|
||||
|
||||
Result of this example is::
|
||||
|
||||
<asyncio.locks.Barrier object at 0x... [filling, waiters:2/3]>
|
||||
<asyncio.locks.Barrier object at 0x... [draining, waiters:0/3]>
|
||||
barrier passed
|
||||
<asyncio.locks.Barrier object at 0x... [filling, waiters:0/3]>
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. coroutinemethod:: wait()
|
||||
|
||||
Pass the barrier. When all the tasks party to the barrier have called
|
||||
this function, they are all unblocked simultaneously.
|
||||
|
||||
When a waiting or blocked task in the barrier is cancelled,
|
||||
this task exits the barrier which stays in the same state.
|
||||
If the state of the barrier is "filling", the number of waiting task
|
||||
decreases by 1.
|
||||
|
||||
The return value is an integer in the range of 0 to ``parties-1``, different
|
||||
for each task. This can be used to select a task to do some special
|
||||
housekeeping, e.g.::
|
||||
|
||||
...
|
||||
async with barrier as position:
|
||||
if position == 0:
|
||||
# Only one task print this
|
||||
print('End of *draining phasis*')
|
||||
|
||||
This method may raise a :class:`BrokenBarrierError` exception if the
|
||||
barrier is broken or reset while a task is waiting.
|
||||
It could raise a :exc:`CancelledError` if a task is cancelled.
|
||||
|
||||
.. coroutinemethod:: reset()
|
||||
|
||||
Return the barrier to the default, empty state. Any tasks waiting on it
|
||||
will receive the :class:`BrokenBarrierError` exception.
|
||||
|
||||
If a barrier is broken it may be better to just leave it and create a new one.
|
||||
|
||||
.. coroutinemethod:: 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 taks needs to abort, to avoid infinite
|
||||
waiting tasks.
|
||||
|
||||
.. attribute:: parties
|
||||
|
||||
The number of tasks required to pass the barrier.
|
||||
|
||||
.. attribute:: n_waiting
|
||||
|
||||
The number of tasks currently waiting in the barrier while filling.
|
||||
|
||||
.. attribute:: broken
|
||||
|
||||
A boolean that is ``True`` if the barrier is in the broken state.
|
||||
|
||||
|
||||
.. exception:: BrokenBarrierError
|
||||
|
||||
This exception, a subclass of :exc:`RuntimeError`, is raised when the
|
||||
:class:`Barrier` object is reset or broken.
|
||||
|
||||
---------
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue