| 49 | |
| 50 | |
| 51 | class AsyncLoopWrapper: |
| 52 | _loop: asyncio.AbstractEventLoop = None |
| 53 | _thread: threading.Thread = None |
| 54 | _logger = init_logger("AsyncLoopWrapper") |
| 55 | |
| 56 | @classmethod |
| 57 | def WaitLoop(cls): |
| 58 | assert cls._loop is not None, "Loop is not started" |
| 59 | |
| 60 | async def wait_for_tasks(): |
| 61 | current_task = asyncio.current_task(cls._loop) |
| 62 | tasks = [ |
| 63 | task |
| 64 | for task in asyncio.all_tasks(cls._loop) |
| 65 | if not task.done() and task is not current_task |
| 66 | ] |
| 67 | cls._logger.info(f"Waiting for {len(tasks)} tasks to finish") |
| 68 | if tasks: |
| 69 | await asyncio.gather(*tasks) |
| 70 | |
| 71 | # Schedule the wait_for_tasks coroutine to be executed in the loop |
| 72 | future = asyncio.run_coroutine_threadsafe(wait_for_tasks(), cls._loop) |
| 73 | try: |
| 74 | # Wait for wait_for_tasks to complete |
| 75 | future.result() |
| 76 | except Exception as e: |
| 77 | cls._logger.error(f"Error while waiting for tasks: {e}") |
| 78 | |
| 79 | @classmethod |
| 80 | def StartLoop(cls): |
| 81 | if cls._loop is not None: |
| 82 | cls._logger.warning("Loop is already started") |
| 83 | return |
| 84 | |
| 85 | if cls._loop is None: |
| 86 | cls._loop = asyncio.new_event_loop() |
| 87 | |
| 88 | def run_loop(): |
| 89 | asyncio.set_event_loop(cls._loop) |
| 90 | cls._logger.debug("Starting the asyncio loop") |
| 91 | cls._loop.run_forever() |
| 92 | |
| 93 | cls._thread = threading.Thread(target=run_loop) |
| 94 | cls._thread.start() |
| 95 | |
| 96 | @classmethod |
| 97 | def StopLoop(cls): |
| 98 | assert cls._loop is not None, "Loop is not started" |
| 99 | assert cls._thread is not None, "Thread is not started" |
| 100 | |
| 101 | def stop_loop(): |
| 102 | cls._logger.debug("Stopping the loop!") |
| 103 | cls._loop.stop() |
| 104 | |
| 105 | cls._logger.info("Waiting for remaining tasks to finish") |
| 106 | cls.WaitLoop() |
| 107 | |
| 108 | cls._loop.call_soon_threadsafe(stop_loop) |
nothing calls this directly
no test coverage detected