import structio import random async def waiter(ch: structio.ChannelReader): print("[waiter] Waiter is alive!") while True: print("[waiter] Awaiting events") try: evt: structio.Event = await ch.receive() except structio.ResourceClosed: break print("[waiter] Received event, waiting to be triggered") t = structio.clock() await evt.wait() print(f"[waiter] Event triggered after {structio.clock() - t:.2f} seconds") print("[waiter] Done!") async def sender(ch: structio.Channel, n: int): print("[sender] Sender is alive!") async with ch: # Channel is automatically closed when exiting # the async with block for _ in range(n): print("[sender] Sending event") ev = structio.Event() await ch.send(ev) t = random.random() print(f"[sender] Sent event, sleeping {t:.2f} seconds") await structio.sleep(t) print("[sender] Setting the event") ev.set() print("[sender] Done!") async def main(n: int): print("[main] Parent is alive") channel = structio.MemoryChannel(1) async with structio.create_pool() as pool: # Each end of the channel can be used independently, # and closing one does not also close the other (which # is why we pass the full channel object to our sender # so it can close both ends and cause the reader to catch # the closing exception and exit cleanly) pool.spawn(waiter, channel.reader) pool.spawn(sender, channel, n) print("[main] Children spawned") print("[main] Done!") structio.run(main, 3)