mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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:
parent
961dbe0548
commit
a0374dd34a
2 changed files with 17 additions and 15 deletions
|
@ -684,8 +684,8 @@ Semaphores also support the :ref:`context management protocol <with-locks>`.
|
||||||
|
|
||||||
.. class:: Semaphore(value=1)
|
.. class:: Semaphore(value=1)
|
||||||
|
|
||||||
This class implements semaphore objects. A semaphore manages a counter
|
This class implements semaphore objects. A semaphore manages an atomic
|
||||||
representing the number of :meth:`release` calls minus the number of
|
counter representing the number of :meth:`release` calls minus the number of
|
||||||
:meth:`acquire` calls, plus an initial value. The :meth:`acquire` method
|
:meth:`acquire` calls, plus an initial value. The :meth:`acquire` method
|
||||||
blocks if necessary until it can return without making the counter negative.
|
blocks if necessary until it can return without making the counter negative.
|
||||||
If not given, *value* defaults to 1.
|
If not given, *value* defaults to 1.
|
||||||
|
@ -701,19 +701,19 @@ Semaphores also support the :ref:`context management protocol <with-locks>`.
|
||||||
|
|
||||||
Acquire a semaphore.
|
Acquire a semaphore.
|
||||||
|
|
||||||
When invoked without arguments: if the internal counter is larger than
|
When invoked without arguments:
|
||||||
zero on entry, decrement it by one and return immediately. If it is zero
|
|
||||||
on entry, block, waiting until some other thread has called
|
* If the internal counter is larger than zero on entry, decrement it by
|
||||||
:meth:`~Semaphore.release` to make it larger than zero. This is done
|
one and return true immediately.
|
||||||
with proper interlocking so that if multiple :meth:`acquire` calls are
|
* If the internal counter is zero on entry, block until awoken by a call to
|
||||||
blocked, :meth:`~Semaphore.release` will wake exactly one of them up.
|
:meth:`~Semaphore.release`. Once awoken (and the counter is greater
|
||||||
The implementation may pick one at random, so the order in which
|
than 0), decrement the counter by 1 and return true. Exactly one
|
||||||
blocked threads are awakened should not be relied on. Returns
|
thread will be awoken by each call to :meth:`~Semaphore.release`. The
|
||||||
true (or blocks indefinitely).
|
order in which threads are awoken should not be relied on.
|
||||||
|
|
||||||
When invoked with *blocking* set to false, do not block. If a call
|
When invoked with *blocking* set to false, do not block. If a call
|
||||||
without an argument would block, return false immediately; otherwise,
|
without an argument would block, return false immediately; otherwise, do
|
||||||
do the same thing as when called without arguments, and return true.
|
the same thing as when called without arguments, and return true.
|
||||||
|
|
||||||
When invoked with a *timeout* other than ``None``, it will block for at
|
When invoked with a *timeout* other than ``None``, it will block for at
|
||||||
most *timeout* seconds. If acquire does not complete successfully in
|
most *timeout* seconds. If acquire does not complete successfully in
|
||||||
|
|
|
@ -629,13 +629,14 @@ class BaseSemaphoreTests(BaseTestCase):
|
||||||
sem = self.semtype(7)
|
sem = self.semtype(7)
|
||||||
sem.acquire()
|
sem.acquire()
|
||||||
N = 10
|
N = 10
|
||||||
|
sem_results = []
|
||||||
results1 = []
|
results1 = []
|
||||||
results2 = []
|
results2 = []
|
||||||
phase_num = 0
|
phase_num = 0
|
||||||
def f():
|
def f():
|
||||||
sem.acquire()
|
sem_results.append(sem.acquire())
|
||||||
results1.append(phase_num)
|
results1.append(phase_num)
|
||||||
sem.acquire()
|
sem_results.append(sem.acquire())
|
||||||
results2.append(phase_num)
|
results2.append(phase_num)
|
||||||
b = Bunch(f, 10)
|
b = Bunch(f, 10)
|
||||||
b.wait_for_started()
|
b.wait_for_started()
|
||||||
|
@ -659,6 +660,7 @@ class BaseSemaphoreTests(BaseTestCase):
|
||||||
# Final release, to let the last thread finish
|
# Final release, to let the last thread finish
|
||||||
sem.release()
|
sem.release()
|
||||||
b.wait_for_finished()
|
b.wait_for_finished()
|
||||||
|
self.assertEqual(sem_results, [True] * (6 + 7 + 6 + 1))
|
||||||
|
|
||||||
def test_try_acquire(self):
|
def test_try_acquire(self):
|
||||||
sem = self.semtype(2)
|
sem = self.semtype(2)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue