Skip to content

Commit

Permalink
Introduce, use a 'never' object
Browse files Browse the repository at this point in the history
This can be used in cases where `await SOMETHING` is required,
but the task cannot be put back on the queue like `await sleep(0)` would
do.

This passes the test and the docs build (locally)
  • Loading branch information
jepler committed Oct 15, 2022
1 parent f22e949 commit c98cff8
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 deletions.
29 changes: 28 additions & 1 deletion asyncio/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ def __next__(self):
self.exc.__traceback__ = None
raise self.exc


# Pause task execution for the given time (integer in milliseconds, uPy extension)
# Use a SingletonGenerator to do it without allocating on the heap
def sleep_ms(t, sgen=SingletonGenerator()):
Expand All @@ -93,6 +92,34 @@ def sleep(t):
return sleep_ms(int(t * 1000))


################################################################################
# "Never schedule" object"
# Don't re-schedule the object that awaits the _never singleton.
# For internal use only. Some constructs, like `await event.wait()`,
# work by NOT re-scheduling the task which calls wait(), but by
# having some other task schedule it later.
class _Never:
def __init__(self):
self.state = None
self.exc = StopIteration()

def __iter__(self):
return self

def __await__(self):
return self

def __next__(self):
if self.state is not None:
self.state = None
return None
else:
self.exc.__traceback__ = None
raise self.exc

_never = _Never()


################################################################################
# Queue and poller for stream IO

Expand Down
3 changes: 2 additions & 1 deletion asyncio/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ async def wait(self):
self.waiting.push_head(core.cur_task)
# Set calling task's data to the event's queue so it can be removed if needed
core.cur_task.data = self.waiting
yield
core._never.state = False
await core._never
return True


Expand Down
3 changes: 2 additions & 1 deletion asyncio/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ async def acquire(self):
# Set calling task's data to the lock's queue so it can be removed if needed
core.cur_task.data = self.waiting
try:
yield
core._never.state = False
await core._never
except core.CancelledError as er:
if self.state == core.cur_task:
# Cancelled while pending on resume, schedule next waiting Task
Expand Down

0 comments on commit c98cff8

Please sign in to comment.