Skip to content

bpo-32208: update threading.Semaphore docs and add unit test #4709

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions Doc/library/threading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -684,8 +684,8 @@ Semaphores also support the :ref:`context management 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
This class implements semaphore objects. A semaphore manages an atomic
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.
Expand All @@ -701,19 +701,19 @@ Semaphores also support the :ref:`context management protocol <with-locks>`.

Acquire a semaphore.

When invoked without arguments: if the internal counter is larger than
zero on entry, decrement it by one and return immediately. If it is zero
on entry, block, waiting until some other thread has called
:meth:`~Semaphore.release` to make it larger than zero. This is done
with proper interlocking so that if multiple :meth:`acquire` calls are
blocked, :meth:`~Semaphore.release` will wake exactly one of them up.
The implementation may pick one at random, so the order in which
blocked threads are awakened should not be relied on. Returns
true (or blocks indefinitely).
When invoked without arguments:

* If the internal counter is larger than zero on entry, decrement it by
one and return true immediately.
* If the internal counter is zero on entry, block until awoken by a call to
:meth:`~Semaphore.release`. Once awoken (and the counter is greater
than 0), decrement the counter by 1 and return true. Exactly one
thread will be awoken by each call to :meth:`~Semaphore.release`. The
order in which threads are awoken should not be relied on.

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.
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
Expand Down
6 changes: 4 additions & 2 deletions Lib/test/lock_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,13 +629,14 @@ def test_acquire_contended(self):
sem = self.semtype(7)
sem.acquire()
N = 10
sem_results = []
results1 = []
results2 = []
phase_num = 0
def f():
sem.acquire()
sem_results.append(sem.acquire())
results1.append(phase_num)
sem.acquire()
sem_results.append(sem.acquire())
results2.append(phase_num)
b = Bunch(f, 10)
b.wait_for_started()
Expand All @@ -659,6 +660,7 @@ def f():
# Final release, to let the last thread finish
sem.release()
b.wait_for_finished()
self.assertEqual(sem_results, [True] * (6 + 7 + 6 + 1))

def test_try_acquire(self):
sem = self.semtype(2)
Expand Down