Skip to content

Commit 6b313de

Browse files
belm0njsmith
andauthored
implement Event directly with wait_task_rescheduled rather than ParkingLot (#1948)
* implement Event directly with wait_task_rescheduled rather than ParkingLot raised in #1944 * clear listening tasks set after rescheduling Co-authored-by: Nathaniel J. Smith <[email protected]> * eliminate use of custom_sleep_data * newsfragment Co-authored-by: Nathaniel J. Smith <[email protected]>
1 parent 7a35ff7 commit 6b313de

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

newsfragments/1948.feature.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Make :class:`~.Event` more lightweight by using less objects (about 2 rather
2+
than 5, including a nested ParkingLot and attribute dicts) and simpler
3+
structures (set rather than OrderedDict). This may benefit applications that
4+
create a large number of event instances, such as with the "replace event
5+
object on every set()" idiom.

trio/_sync.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import math
22

33
import attr
4-
import outcome
54

65
import trio
76

7+
from . import _core
88
from ._core import enable_ki_protection, ParkingLot
9-
from ._deprecate import deprecated
109
from ._util import Final
1110

1211

13-
@attr.s(repr=False, eq=False, hash=False)
12+
@attr.s(frozen=True)
13+
class _EventStatistics:
14+
tasks_waiting = attr.ib()
15+
16+
17+
@attr.s(repr=False, eq=False, hash=False, slots=True)
1418
class Event(metaclass=Final):
1519
"""A waitable boolean value useful for inter-task synchronization,
1620
inspired by :class:`threading.Event`.
@@ -37,7 +41,7 @@ class Event(metaclass=Final):
3741
3842
"""
3943

40-
_lot = attr.ib(factory=ParkingLot, init=False)
44+
_tasks = attr.ib(factory=set, init=False)
4145
_flag = attr.ib(default=False, init=False)
4246

4347
def is_set(self):
@@ -47,8 +51,11 @@ def is_set(self):
4751
@enable_ki_protection
4852
def set(self):
4953
"""Set the internal flag value to True, and wake any waiting tasks."""
50-
self._flag = True
51-
self._lot.unpark_all()
54+
if not self._flag:
55+
self._flag = True
56+
for task in self._tasks:
57+
_core.reschedule(task)
58+
self._tasks.clear()
5259

5360
async def wait(self):
5461
"""Block until the internal flag value becomes True.
@@ -59,7 +66,14 @@ async def wait(self):
5966
if self._flag:
6067
await trio.lowlevel.checkpoint()
6168
else:
62-
await self._lot.park()
69+
task = _core.current_task()
70+
self._tasks.add(task)
71+
72+
def abort_fn(_):
73+
self._tasks.remove(task)
74+
return _core.Abort.SUCCEEDED
75+
76+
await _core.wait_task_rescheduled(abort_fn)
6377

6478
def statistics(self):
6579
"""Return an object containing debugging information.
@@ -70,7 +84,7 @@ def statistics(self):
7084
:meth:`wait` method.
7185
7286
"""
73-
return self._lot.statistics()
87+
return _EventStatistics(tasks_waiting=len(self._tasks))
7488

7589

7690
def async_cm(cls):

0 commit comments

Comments
 (0)