| f | import asyncio | f | import asyncio |
| | | |
| class Loop: | | class Loop: |
| n | _count = 0 | n | _registry_count = 0 |
| _funcs = [] | | _registry_funcs = [] |
| _call_args = [] | | _registry_args = [] |
| _started = 0 | | _registry_started = 0 |
| _all_started_event = None | | _all_started_event = None |
| n | _done_fut = None | n | _finished_future = None |
| _scheduler_running = False | | _scheduler_active = False |
| | | |
| def __init__(self): | | def __init__(self): |
| pass | | pass |
| | | |
| n | def __call__(self, func): | n | def __call__(self, coro_func): |
| cls = self.__class__ | | cls = self.__class__ |
| n | idx = cls._count | n | my_idx = cls._registry_count |
| cls._count += 1 | | cls._registry_count += 1 |
| cls._funcs.append(func) | | cls._registry_funcs.append(coro_func) |
| if len(cls._call_args) < cls._count: | | if len(cls._registry_args) < cls._registry_count: |
| cls._call_args.append(None) | | cls._registry_args.append(None) |
| | | |
| async def wrapper(*args, **kwargs): | | async def wrapper(*args, **kwargs): |
| n | cls = self.__class__ | n | |
| loop = asyncio.get_running_loop() | | loop = asyncio.get_running_loop() |
| n | if cls._done_fut is None: | n | if cls._finished_future is None: |
| cls._done_fut = loop.create_future() | | cls._finished_future = loop.create_future() |
| if cls._all_started_event is None: | | if cls._all_started_event is None: |
| cls._all_started_event = asyncio.Event() | | cls._all_started_event = asyncio.Event() |
| n | cls._call_args[idx] = (args, kwargs) | n | cls._registry_args[my_idx] = (args, kwargs) |
| cls._started += 1 | | cls._registry_started += 1 |
| if cls._scheduler_running: | | if cls._scheduler_active: |
| if cls._started == cls._count: | | if cls._registry_started == cls._registry_count: |
| cls._all_started_event.set() | | cls._all_started_event.set() |
| n | await cls._done_fut | n | await cls._finished_future |
| return None | | return None |
| n | cls._scheduler_running = True | n | cls._scheduler_active = True |
| try: | | try: |
| n | if cls._started < cls._count: | n | if cls._registry_started < cls._registry_count: |
| await cls._all_started_event.wait() | | await cls._all_started_event.wait() |
| else: | | else: |
| cls._all_started_event.set() | | cls._all_started_event.set() |
| n | idx_local = 0 | n | idx_cycle = 0 |
| while True: | | while True: |
| n | func_local = cls._funcs[idx_local] | n | func = cls._registry_funcs[idx_cycle] |
| args_local, kwargs_local = cls._call_args[idx_local] | | args_cycle, kwargs_cycle = cls._registry_args[idx_cy |
| | | cle] |
| res = await func_local(*args_local, **kwargs_local) | | result = await func(*args_cycle, **kwargs_cycle) |
| if res is None: | | if result is None: |
| break | | break |
| n | idx_local = (idx_local + 1) % cls._count | n | idx_cycle = (idx_cycle + 1) % cls._registry_count |
| if not cls._done_fut.done(): | | if not cls._finished_future.done(): |
| cls._done_fut.set_result(None) | | cls._finished_future.set_result(None) |
| finally: | | finally: |
| n | cls._scheduler_running = False | n | cls._scheduler_active = False |
| cls._count = 0 | | cls._registry_count = 0 |
| cls._funcs = [] | | cls._registry_funcs = [] |
| cls._call_args = [] | | cls._registry_args = [] |
| cls._started = 0 | | cls._registry_started = 0 |
| cls._all_started_event = None | | cls._all_started_event = None |
| t | cls._done_fut = None | t | cls._finished_future = None |
| return None | | return None |
| return wrapper | | return wrapper |