mirror of
https://github.com/python/cpython.git
synced 2025-10-07 15:42:02 +00:00
Issue #850728: Add a *timeout* parameter to the acquire()
method of
`threading.Semaphore` objects. Original patch by Torsten Landschoff.
This commit is contained in:
parent
2d9cb9c1cb
commit
0454af9b54
5 changed files with 40 additions and 9 deletions
|
@ -596,7 +596,7 @@ waiting until some other thread calls :meth:`release`.
|
||||||
defaults to ``1``. If the *value* given is less than 0, :exc:`ValueError` is
|
defaults to ``1``. If the *value* given is less than 0, :exc:`ValueError` is
|
||||||
raised.
|
raised.
|
||||||
|
|
||||||
.. method:: acquire(blocking=True)
|
.. method:: acquire(blocking=True, timeout=None)
|
||||||
|
|
||||||
Acquire a semaphore.
|
Acquire a semaphore.
|
||||||
|
|
||||||
|
@ -607,14 +607,18 @@ waiting until some other thread calls :meth:`release`.
|
||||||
interlocking so that if multiple :meth:`acquire` calls are blocked,
|
interlocking so that if multiple :meth:`acquire` calls are blocked,
|
||||||
:meth:`release` will wake exactly one of them up. The implementation may
|
:meth:`release` will wake exactly one of them up. The implementation may
|
||||||
pick one at random, so the order in which blocked threads are awakened
|
pick one at random, so the order in which blocked threads are awakened
|
||||||
should not be relied on. There is no return value in this case.
|
should not be relied on. Returns true (or blocks indefinitely).
|
||||||
|
|
||||||
When invoked with *blocking* set to true, do the same thing as when called
|
|
||||||
without arguments, and return true.
|
|
||||||
|
|
||||||
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, do
|
without an argument would block, return false immediately; otherwise,
|
||||||
the same thing as when called without arguments, and return true.
|
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
|
||||||
|
that interval, return false. Return true otherwise.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2
|
||||||
|
The *timeout* parameter is new.
|
||||||
|
|
||||||
.. method:: release()
|
.. method:: release()
|
||||||
|
|
||||||
|
|
|
@ -521,6 +521,19 @@ class BaseSemaphoreTests(BaseTestCase):
|
||||||
# ordered.
|
# ordered.
|
||||||
self.assertEqual(sorted(results), [False] * 7 + [True] * 3 )
|
self.assertEqual(sorted(results), [False] * 7 + [True] * 3 )
|
||||||
|
|
||||||
|
def test_acquire_timeout(self):
|
||||||
|
sem = self.semtype(2)
|
||||||
|
self.assertRaises(ValueError, sem.acquire, False, timeout=1.0)
|
||||||
|
self.assertTrue(sem.acquire(timeout=0.005))
|
||||||
|
self.assertTrue(sem.acquire(timeout=0.005))
|
||||||
|
self.assertFalse(sem.acquire(timeout=0.005))
|
||||||
|
sem.release()
|
||||||
|
self.assertTrue(sem.acquire(timeout=0.005))
|
||||||
|
t = time.time()
|
||||||
|
self.assertFalse(sem.acquire(timeout=0.5))
|
||||||
|
dt = time.time() - t
|
||||||
|
self.assertTimeout(dt, 0.5)
|
||||||
|
|
||||||
def test_default_value(self):
|
def test_default_value(self):
|
||||||
# The default initial value is 1.
|
# The default initial value is 1.
|
||||||
sem = self.semtype()
|
sem = self.semtype()
|
||||||
|
|
|
@ -290,8 +290,11 @@ class _Semaphore(_Verbose):
|
||||||
self._cond = Condition(Lock())
|
self._cond = Condition(Lock())
|
||||||
self._value = value
|
self._value = value
|
||||||
|
|
||||||
def acquire(self, blocking=True):
|
def acquire(self, blocking=True, timeout=None):
|
||||||
|
if not blocking and timeout is not None:
|
||||||
|
raise ValueError("can't specify timeout for non-blocking acquire")
|
||||||
rc = False
|
rc = False
|
||||||
|
endtime = None
|
||||||
self._cond.acquire()
|
self._cond.acquire()
|
||||||
while self._value == 0:
|
while self._value == 0:
|
||||||
if not blocking:
|
if not blocking:
|
||||||
|
@ -299,7 +302,14 @@ class _Semaphore(_Verbose):
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._note("%s.acquire(%s): blocked waiting, value=%s",
|
self._note("%s.acquire(%s): blocked waiting, value=%s",
|
||||||
self, blocking, self._value)
|
self, blocking, self._value)
|
||||||
self._cond.wait()
|
if timeout is not None:
|
||||||
|
if endtime is None:
|
||||||
|
endtime = _time() + timeout
|
||||||
|
else:
|
||||||
|
timeout = endtime - _time()
|
||||||
|
if timeout <= 0:
|
||||||
|
break
|
||||||
|
self._cond.wait(timeout)
|
||||||
else:
|
else:
|
||||||
self._value = self._value - 1
|
self._value = self._value - 1
|
||||||
if __debug__:
|
if __debug__:
|
||||||
|
|
|
@ -431,6 +431,7 @@ Ivan Krstić
|
||||||
Andrew Kuchling
|
Andrew Kuchling
|
||||||
Vladimir Kushnir
|
Vladimir Kushnir
|
||||||
Cameron Laird
|
Cameron Laird
|
||||||
|
Torsten Landschoff
|
||||||
Tino Lange
|
Tino Lange
|
||||||
Andrew Langmead
|
Andrew Langmead
|
||||||
Detlef Lannert
|
Detlef Lannert
|
||||||
|
|
|
@ -315,6 +315,9 @@ C-API
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #850728: Add a *timeout* parameter to the `acquire()` method of
|
||||||
|
`threading.Semaphore` objects. Patch by Torsten Landschoff.
|
||||||
|
|
||||||
- Issue #8322: Add a *ciphers* argument to SSL sockets, so as to change the
|
- Issue #8322: Add a *ciphers* argument to SSL sockets, so as to change the
|
||||||
available cipher list. Helps fix test_ssl with OpenSSL 1.0.0.
|
available cipher list. Helps fix test_ssl with OpenSSL 1.0.0.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue