diff options
author | Jim Mussared <jim.mussared@gmail.com> | 2023-06-08 15:51:50 +1000 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2023-06-19 17:33:03 +1000 |
commit | 2fbc08c462e247e7f78460783c9a07c76c5b762e (patch) | |
tree | cfda4eb3b04a6cc281fb0ea668a15b6216353c16 /extmod/asyncio/lock.py | |
parent | ed962f1f233eb74edf2cee83dc488d3cac5e02ee (diff) |
extmod/asyncio: Rename uasyncio to asyncio.
The asyncio module now has much better CPython compatibility and
deserves to be just called "asyncio".
This will avoid people having to write `from uasyncio import asyncio`.
Renames all files, and updates port manifests to use the new path. Also
renames the built-in _uasyncio to _asyncio.
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Diffstat (limited to 'extmod/asyncio/lock.py')
-rw-r--r-- | extmod/asyncio/lock.py | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/extmod/asyncio/lock.py b/extmod/asyncio/lock.py new file mode 100644 index 000000000..0a46ac326 --- /dev/null +++ b/extmod/asyncio/lock.py @@ -0,0 +1,55 @@ +# MicroPython asyncio module +# MIT license; Copyright (c) 2019-2020 Damien P. George + +from . import core + + +# Lock class for primitive mutex capability +class Lock: + def __init__(self): + # The state can take the following values: + # - 0: unlocked + # - 1: locked + # - <Task>: unlocked but this task has been scheduled to acquire the lock next + self.state = 0 + # Queue of Tasks waiting to acquire this Lock + self.waiting = core.TaskQueue() + + def locked(self): + return self.state == 1 + + def release(self): + if self.state != 1: + raise RuntimeError("Lock not acquired") + if self.waiting.peek(): + # Task(s) waiting on lock, schedule next Task + self.state = self.waiting.pop() + core._task_queue.push(self.state) + else: + # No Task waiting so unlock + self.state = 0 + + # async + def acquire(self): + if self.state != 0: + # Lock unavailable, put the calling Task on the waiting queue + self.waiting.push(core.cur_task) + # 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 + except core.CancelledError as er: + if self.state == core.cur_task: + # Cancelled while pending on resume, schedule next waiting Task + self.state = 1 + self.release() + raise er + # Lock available, set it as locked + self.state = 1 + return True + + async def __aenter__(self): + return await self.acquire() + + async def __aexit__(self, exc_type, exc, tb): + return self.release() |