mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
#10218: return timeout status from Condition.wait, mirroring other primitives' behavior.
This commit is contained in:
parent
cbb9421347
commit
b9a4391754
4 changed files with 29 additions and 13 deletions
|
@ -574,6 +574,12 @@ needs to wake up one consumer thread.
|
||||||
interface is then used to restore the recursion level when the lock is
|
interface is then used to restore the recursion level when the lock is
|
||||||
reacquired.
|
reacquired.
|
||||||
|
|
||||||
|
The return value is ``True`` unless a given *timeout* expired, in which
|
||||||
|
case it is ``False``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2
|
||||||
|
Previously, the method always returned ``None``.
|
||||||
|
|
||||||
.. method:: notify()
|
.. method:: notify()
|
||||||
|
|
||||||
Wake up a thread waiting on this condition, if any. If the calling thread
|
Wake up a thread waiting on this condition, if any. If the calling thread
|
||||||
|
|
|
@ -375,13 +375,13 @@ class ConditionTests(BaseTestCase):
|
||||||
phase_num = 0
|
phase_num = 0
|
||||||
def f():
|
def f():
|
||||||
cond.acquire()
|
cond.acquire()
|
||||||
cond.wait()
|
result = cond.wait()
|
||||||
cond.release()
|
cond.release()
|
||||||
results1.append(phase_num)
|
results1.append((result, phase_num))
|
||||||
cond.acquire()
|
cond.acquire()
|
||||||
cond.wait()
|
result = cond.wait()
|
||||||
cond.release()
|
cond.release()
|
||||||
results2.append(phase_num)
|
results2.append((result, phase_num))
|
||||||
b = Bunch(f, N)
|
b = Bunch(f, N)
|
||||||
b.wait_for_started()
|
b.wait_for_started()
|
||||||
_wait()
|
_wait()
|
||||||
|
@ -394,7 +394,7 @@ class ConditionTests(BaseTestCase):
|
||||||
cond.release()
|
cond.release()
|
||||||
while len(results1) < 3:
|
while len(results1) < 3:
|
||||||
_wait()
|
_wait()
|
||||||
self.assertEqual(results1, [1] * 3)
|
self.assertEqual(results1, [(True, 1)] * 3)
|
||||||
self.assertEqual(results2, [])
|
self.assertEqual(results2, [])
|
||||||
# Notify 5 threads: they might be in their first or second wait
|
# Notify 5 threads: they might be in their first or second wait
|
||||||
cond.acquire()
|
cond.acquire()
|
||||||
|
@ -404,8 +404,8 @@ class ConditionTests(BaseTestCase):
|
||||||
cond.release()
|
cond.release()
|
||||||
while len(results1) + len(results2) < 8:
|
while len(results1) + len(results2) < 8:
|
||||||
_wait()
|
_wait()
|
||||||
self.assertEqual(results1, [1] * 3 + [2] * 2)
|
self.assertEqual(results1, [(True, 1)] * 3 + [(True, 2)] * 2)
|
||||||
self.assertEqual(results2, [2] * 3)
|
self.assertEqual(results2, [(True, 2)] * 3)
|
||||||
# Notify all threads: they are all in their second wait
|
# Notify all threads: they are all in their second wait
|
||||||
cond.acquire()
|
cond.acquire()
|
||||||
cond.notify_all()
|
cond.notify_all()
|
||||||
|
@ -414,8 +414,8 @@ class ConditionTests(BaseTestCase):
|
||||||
cond.release()
|
cond.release()
|
||||||
while len(results2) < 5:
|
while len(results2) < 5:
|
||||||
_wait()
|
_wait()
|
||||||
self.assertEqual(results1, [1] * 3 + [2] * 2)
|
self.assertEqual(results1, [(True, 1)] * 3 + [(True,2)] * 2)
|
||||||
self.assertEqual(results2, [2] * 3 + [3] * 2)
|
self.assertEqual(results2, [(True, 2)] * 3 + [(True, 3)] * 2)
|
||||||
b.wait_for_finished()
|
b.wait_for_finished()
|
||||||
|
|
||||||
def test_notify(self):
|
def test_notify(self):
|
||||||
|
@ -431,14 +431,20 @@ class ConditionTests(BaseTestCase):
|
||||||
def f():
|
def f():
|
||||||
cond.acquire()
|
cond.acquire()
|
||||||
t1 = time.time()
|
t1 = time.time()
|
||||||
cond.wait(0.5)
|
result = cond.wait(0.5)
|
||||||
t2 = time.time()
|
t2 = time.time()
|
||||||
cond.release()
|
cond.release()
|
||||||
results.append(t2 - t1)
|
results.append((t2 - t1, result))
|
||||||
Bunch(f, N).wait_for_finished()
|
Bunch(f, N).wait_for_finished()
|
||||||
self.assertEqual(len(results), 5)
|
self.assertEqual(len(results), N)
|
||||||
for dt in results:
|
for dt, result in results:
|
||||||
self.assertTimeout(dt, 0.5)
|
self.assertTimeout(dt, 0.5)
|
||||||
|
# Note that conceptually (that"s the condition variable protocol)
|
||||||
|
# a wait() may succeed even if no one notifies us and before any
|
||||||
|
# timeout occurs. Spurious wakeups can occur.
|
||||||
|
# This makes it hard to verify the result value.
|
||||||
|
# In practice, this implementation has no spurious wakeups.
|
||||||
|
self.assertFalse(result)
|
||||||
|
|
||||||
|
|
||||||
class BaseSemaphoreTests(BaseTestCase):
|
class BaseSemaphoreTests(BaseTestCase):
|
||||||
|
|
|
@ -232,6 +232,7 @@ class _Condition(_Verbose):
|
||||||
try: # restore state no matter what (e.g., KeyboardInterrupt)
|
try: # restore state no matter what (e.g., KeyboardInterrupt)
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
waiter.acquire()
|
waiter.acquire()
|
||||||
|
gotit = True
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._note("%s.wait(): got it", self)
|
self._note("%s.wait(): got it", self)
|
||||||
else:
|
else:
|
||||||
|
@ -249,6 +250,7 @@ class _Condition(_Verbose):
|
||||||
else:
|
else:
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._note("%s.wait(%s): got it", self, timeout)
|
self._note("%s.wait(%s): got it", self, timeout)
|
||||||
|
return gotit
|
||||||
finally:
|
finally:
|
||||||
self._acquire_restore(saved_state)
|
self._acquire_restore(saved_state)
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #10218: Return timeout status from ``Condition.wait`` in threading.
|
||||||
|
|
||||||
- Issue #7351: Add ``zipfile.BadZipFile`` spelling of the exception name
|
- Issue #7351: Add ``zipfile.BadZipFile`` spelling of the exception name
|
||||||
and deprecate the old name ``zipfile.BadZipfile``.
|
and deprecate the old name ``zipfile.BadZipfile``.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue