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

* fix issue32208: update threading.Semaphore docs and add unit test to validate correct behavior

* add test for blocking

* Update threading.rst

* semaphore: remove documentation validation tests and move 'return value' test to BaseSemaphore
This commit is contained in:
Garrett Berg 2017-12-07 11:04:26 -07:00 committed by Andrew Svetlov
parent 961dbe0548
commit a0374dd34a
2 changed files with 17 additions and 15 deletions

View File

@ -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.
@ -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

View File

@ -629,13 +629,14 @@ class BaseSemaphoreTests(BaseTestCase):
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()
@ -659,6 +660,7 @@ class BaseSemaphoreTests(BaseTestCase):
# 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)