summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/library/uasyncio.rst6
-rw-r--r--extmod/uasyncio/core.py18
-rw-r--r--tests/extmod/uasyncio_loop_stop.py45
-rw-r--r--tests/extmod/uasyncio_loop_stop.py.exp7
4 files changed, 74 insertions, 2 deletions
diff --git a/docs/library/uasyncio.rst b/docs/library/uasyncio.rst
index ebe0c34eb..ff3232ebd 100644
--- a/docs/library/uasyncio.rst
+++ b/docs/library/uasyncio.rst
@@ -251,13 +251,17 @@ Event Loop
.. method:: Loop.run_forever()
- Run the event loop forever.
+ Run the event loop until `stop()` is called.
.. method:: Loop.run_until_complete(awaitable)
Run the given *awaitable* until it completes. If *awaitable* is not a task
then it will be promoted to one.
+.. method:: Loop.stop()
+
+ Stop the event loop.
+
.. method:: Loop.close()
Close the event loop.
diff --git a/extmod/uasyncio/core.py b/extmod/uasyncio/core.py
index 4a8597a3f..dd0229ee4 100644
--- a/extmod/uasyncio/core.py
+++ b/extmod/uasyncio/core.py
@@ -214,17 +214,33 @@ def run(coro):
# Event loop wrapper
+async def _stopper():
+ pass
+
+
+_stop_task = None
+
+
class Loop:
def create_task(coro):
return create_task(coro)
def run_forever():
- run_until_complete()
+ global _stop_task
+ _stop_task = Task(_stopper(), globals())
+ run_until_complete(_stop_task)
# TODO should keep running until .stop() is called, even if there're no tasks left
def run_until_complete(aw):
return run_until_complete(_promote_to_task(aw))
+ def stop():
+ global _stop_task
+ if _stop_task is not None:
+ _task_queue.push_head(_stop_task)
+ # If stop() is called again, do nothing
+ _stop_task = None
+
def close():
pass
diff --git a/tests/extmod/uasyncio_loop_stop.py b/tests/extmod/uasyncio_loop_stop.py
new file mode 100644
index 000000000..23507f9a7
--- /dev/null
+++ b/tests/extmod/uasyncio_loop_stop.py
@@ -0,0 +1,45 @@
+# Test Loop.stop() to stop the event loop
+
+try:
+ import uasyncio as asyncio
+except ImportError:
+ try:
+ import asyncio
+ except ImportError:
+ print("SKIP")
+ raise SystemExit
+
+
+async def task():
+ print("task")
+
+
+async def main():
+ print("start")
+
+ # Stop the loop after next yield
+ loop.stop()
+
+ # Check that calling stop() again doesn't do/break anything
+ loop.stop()
+
+ # This await should stop
+ print("sleep")
+ await asyncio.sleep(0)
+
+ # Schedule stop, then create a new task, then yield
+ loop.stop()
+ asyncio.create_task(task())
+ await asyncio.sleep(0)
+
+ # Final stop
+ print("end")
+ loop.stop()
+
+
+loop = asyncio.get_event_loop()
+loop.create_task(main())
+
+for i in range(3):
+ print("run", i)
+ loop.run_forever()
diff --git a/tests/extmod/uasyncio_loop_stop.py.exp b/tests/extmod/uasyncio_loop_stop.py.exp
new file mode 100644
index 000000000..bada5f0d8
--- /dev/null
+++ b/tests/extmod/uasyncio_loop_stop.py.exp
@@ -0,0 +1,7 @@
+run 0
+start
+sleep
+run 1
+run 2
+task
+end