/v3/primitives/condition.py

https://github.com/peterhinch/micropython-async · Python · 68 lines · 46 code · 15 blank · 7 comment · 8 complexity · 4e4716f8425ad91a9770636a22d3a420 MD5 · raw file

  1. # condition.py
  2. # Copyright (c) 2018-2020 Peter Hinch
  3. # Released under the MIT License (MIT) - see LICENSE file
  4. try:
  5. import uasyncio as asyncio
  6. except ImportError:
  7. import asyncio
  8. # Condition class
  9. # from primitives.condition import Condition
  10. class Condition():
  11. def __init__(self, lock=None):
  12. self.lock = asyncio.Lock() if lock is None else lock
  13. self.events = []
  14. async def acquire(self):
  15. await self.lock.acquire()
  16. # enable this syntax:
  17. # with await condition [as cond]:
  18. def __await__(self):
  19. await self.lock.acquire()
  20. return self
  21. __iter__ = __await__
  22. def __enter__(self):
  23. return self
  24. def __exit__(self, *_):
  25. self.lock.release()
  26. def locked(self):
  27. return self.lock.locked()
  28. def release(self):
  29. self.lock.release() # Will raise RuntimeError if not locked
  30. def notify(self, n=1): # Caller controls lock
  31. if not self.lock.locked():
  32. raise RuntimeError('Condition notify with lock not acquired.')
  33. for _ in range(min(n, len(self.events))):
  34. ev = self.events.pop()
  35. ev.set()
  36. def notify_all(self):
  37. self.notify(len(self.events))
  38. async def wait(self):
  39. if not self.lock.locked():
  40. raise RuntimeError('Condition wait with lock not acquired.')
  41. ev = asyncio.Event()
  42. self.events.append(ev)
  43. self.lock.release()
  44. await ev.wait()
  45. await self.lock.acquire()
  46. assert ev not in self.events, 'condition wait assertion fail'
  47. return True # CPython compatibility
  48. async def wait_for(self, predicate):
  49. result = predicate()
  50. while not result:
  51. await self.wait()
  52. result = predicate()
  53. return result