1# MicroPython uasyncio module 2# MIT license; Copyright (c) 2019-2020 Damien P. George 3 4from . import core 5 6# Event class for primitive events that can be waited on, set, and cleared 7class Event: 8 def __init__(self): 9 self.state = False # False=unset; True=set 10 self.waiting = core.TaskQueue() # Queue of Tasks waiting on completion of this event 11 12 def is_set(self): 13 return self.state 14 15 def set(self): 16 # Event becomes set, schedule any tasks waiting on it 17 # Note: This must not be called from anything except the thread running 18 # the asyncio loop (i.e. neither hard or soft IRQ, or a different thread). 19 while self.waiting.peek(): 20 core._task_queue.push_head(self.waiting.pop_head()) 21 self.state = True 22 23 def clear(self): 24 self.state = False 25 26 async def wait(self): 27 if not self.state: 28 # Event not set, put the calling task on the event's waiting queue 29 self.waiting.push_head(core.cur_task) 30 # Set calling task's data to the event's queue so it can be removed if needed 31 core.cur_task.data = self.waiting 32 yield 33 return True 34 35 36# MicroPython-extension: This can be set from outside the asyncio event loop, 37# such as other threads, IRQs or scheduler context. Implementation is a stream 38# that asyncio will poll until a flag is set. 39# Note: Unlike Event, this is self-clearing. 40try: 41 import uio 42 43 class ThreadSafeFlag(uio.IOBase): 44 def __init__(self): 45 self._flag = 0 46 47 def ioctl(self, req, flags): 48 if req == 3: # MP_STREAM_POLL 49 return self._flag * flags 50 return None 51 52 def set(self): 53 self._flag = 1 54 55 async def wait(self): 56 if not self._flag: 57 yield core._io_queue.queue_read(self) 58 self._flag = 0 59 60 61except ImportError: 62 pass 63