Skip to content

Commit ee2ece3

Browse files
gh-148489: Lazy-init _waiters in asyncio Event and Condition
Apply the same lazy initialization pattern used by Lock and Semaphore (introduced in GH-97545) to Event and Condition. Initialize _waiters to None instead of collections.deque(), deferring the allocation to the first wait() call. This avoids an unnecessary deque allocation for primitives that are created but never contended on.
1 parent 8fc66ae commit ee2ece3

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

Lib/asyncio/locks.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class Event(mixins._LoopBoundMixin):
165165
"""
166166

167167
def __init__(self):
168-
self._waiters = collections.deque()
168+
self._waiters = None
169169
self._value = False
170170

171171
def __repr__(self):
@@ -187,9 +187,10 @@ def set(self):
187187
if not self._value:
188188
self._value = True
189189

190-
for fut in self._waiters:
191-
if not fut.done():
192-
fut.set_result(True)
190+
if self._waiters:
191+
for fut in self._waiters:
192+
if not fut.done():
193+
fut.set_result(True)
193194

194195
def clear(self):
195196
"""Reset the internal flag to false. Subsequently, tasks calling
@@ -207,6 +208,8 @@ async def wait(self):
207208
if self._value:
208209
return True
209210

211+
if self._waiters is None:
212+
self._waiters = collections.deque()
210213
fut = self._get_loop().create_future()
211214
self._waiters.append(fut)
212215
try:
@@ -236,7 +239,7 @@ def __init__(self, lock=None):
236239
self.acquire = lock.acquire
237240
self.release = lock.release
238241

239-
self._waiters = collections.deque()
242+
self._waiters = None
240243

241244
def __repr__(self):
242245
res = super().__repr__()
@@ -263,6 +266,8 @@ async def wait(self):
263266
if not self.locked():
264267
raise RuntimeError('cannot wait on un-acquired lock')
265268

269+
if self._waiters is None:
270+
self._waiters = collections.deque()
266271
fut = self._get_loop().create_future()
267272
self.release()
268273
try:
@@ -331,6 +336,8 @@ def notify(self, n=1):
331336
self._notify(n)
332337

333338
def _notify(self, n):
339+
if not self._waiters:
340+
return
334341
idx = 0
335342
for fut in self._waiters:
336343
if idx >= n:
@@ -346,7 +353,7 @@ def notify_all(self):
346353
calling task has not acquired the lock when this method is called,
347354
a RuntimeError is raised.
348355
"""
349-
self.notify(len(self._waiters))
356+
self.notify(len(self._waiters or ()))
350357

351358

352359
class Semaphore(_ContextManagerMixin, mixins._LoopBoundMixin):

0 commit comments

Comments
 (0)