Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9c80b55

Browse files
miss-islingtoncykerway
authored andcommitted
gh-97545: Make Semaphore run faster. (GH-97549)
(cherry picked from commit 68c46ae) Co-authored-by: Cyker Way <[email protected]>
1 parent 56145c6 commit 9c80b55

File tree

3 files changed

+19
-23
lines changed

3 files changed

+19
-23
lines changed

Lib/asyncio/locks.py

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,9 @@ def __repr__(self):
357357
return f'<{res[1:-1]} [{extra}]>'
358358

359359
def locked(self):
360-
"""Returns True if semaphore counter is zero."""
361-
return self._value == 0
360+
"""Returns True if semaphore cannot be acquired immediately."""
361+
return self._value == 0 or (
362+
any(not w.cancelled() for w in (self._waiters or ())))
362363

363364
async def acquire(self):
364365
"""Acquire a semaphore.
@@ -369,8 +370,7 @@ async def acquire(self):
369370
called release() to make it larger than 0, and then return
370371
True.
371372
"""
372-
if (not self.locked() and (self._waiters is None or
373-
all(w.cancelled() for w in self._waiters))):
373+
if not self.locked():
374374
self._value -= 1
375375
return True
376376

@@ -388,13 +388,13 @@ async def acquire(self):
388388
finally:
389389
self._waiters.remove(fut)
390390
except exceptions.CancelledError:
391-
if not self.locked():
392-
self._wake_up_first()
391+
if not fut.cancelled():
392+
self._value += 1
393+
self._wake_up_next()
393394
raise
394395

395-
self._value -= 1
396-
if not self.locked():
397-
self._wake_up_first()
396+
if self._value > 0:
397+
self._wake_up_next()
398398
return True
399399

400400
def release(self):
@@ -404,22 +404,18 @@ def release(self):
404404
become larger than zero again, wake up that coroutine.
405405
"""
406406
self._value += 1
407-
self._wake_up_first()
407+
self._wake_up_next()
408408

409-
def _wake_up_first(self):
410-
"""Wake up the first waiter if it isn't done."""
409+
def _wake_up_next(self):
410+
"""Wake up the first waiter that isn't done."""
411411
if not self._waiters:
412412
return
413-
try:
414-
fut = next(iter(self._waiters))
415-
except StopIteration:
416-
return
417413

418-
# .done() necessarily means that a waiter will wake up later on and
419-
# either take the lock, or, if it was cancelled and lock wasn't
420-
# taken already, will hit this again and wake up a new waiter.
421-
if not fut.done():
422-
fut.set_result(True)
414+
for fut in self._waiters:
415+
if not fut.done():
416+
self._value -= 1
417+
fut.set_result(True)
418+
return
423419

424420

425421
class BoundedSemaphore(Semaphore):

Lib/test/test_asyncio/test_locks.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,9 +844,8 @@ async def c4(result):
844844

845845
sem.release()
846846
sem.release()
847-
self.assertEqual(2, sem._value)
847+
self.assertEqual(0, sem._value)
848848

849-
await asyncio.sleep(0)
850849
await asyncio.sleep(0)
851850
self.assertEqual(0, sem._value)
852851
self.assertEqual(3, len(result))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make Semaphore run faster.

0 commit comments

Comments
 (0)