Морозов Иван Дмитриевич, 517 GroupWork 11254
Зыков Валерий Павлович, 517 GroupWork 11251
f1import asynciof1import asyncio
2from collections import deque2from collections import deque
33
4class Loop:4class Loop:
nn5    """Параметрический декоратор для корутин с синхронизацией выполнения
 >"""
6    _coros = []
5    _tasks = []7    _args_kwargs = []
6    _params = []
7    _cursor = 08    _current = 0
9    _done = False
8    _finished = False10    _scheduled = False
9    _active = False
1011
11    def __init__(self):12    def __init__(self):
n12        self._id = len(Loop._tasks)n13        self.index = len(Loop._coros)
13        Loop._tasks.append(None)
14        Loop._params.append(None)14        Loop._coros.append(None)
15        Loop._args_kwargs.append(None)
1516
n16    def __call__(self, fn):n17    def __call__(self, coro):
17        Loop._tasks[self._id] = fn18        Loop._coros[self.index] = coro
1819
n19        async def launcher(*args, **kwargs):n20        async def wrapper(*args, **kwargs):
20            Loop._params[self._id] = (args, kwargs)21            Loop._args_kwargs[self.index] = (args, kwargs)
21            if not Loop._active:22            if not Loop._scheduled:
22                Loop._active = True23                Loop._scheduled = True
23                return await Loop._run_scheduler()24                return await Loop._run_scheduler()
24            return None25            return None
n25        return launchern26        return wrapper
2627
27    @classmethod28    @classmethod
28    async def _run_scheduler(cls):29    async def _run_scheduler(cls):
nn30        """Планировщик, который выполняет все корутины по очереди"""
29        pointer = 031        step = 0
30        count = len(cls._tasks)32        total_coros = len(cls._coros)
31        while not cls._finished:33        while not cls._done:
32            slot = pointer % count34            idx = step % total_coros
33            task = cls._tasks[slot]35            coro = cls._coros[idx]
34            payload = cls._params[slot]36            args_kwargs = cls._args_kwargs[idx]
35            if task is None or payload is None:37            if coro is None or args_kwargs is None:
36                pointer += 138                step += 1
37                await asyncio.sleep(0)39                await asyncio.sleep(0)
38                continue40                continue
n39            args, kwargs = payloadn41            args, kwargs = args_kwargs
40            try:42            try:
n41                outcome = await task(*args, **kwargs)n43                result = await coro(*args, **kwargs)
42            except asyncio.CancelledError:44            except asyncio.CancelledError:
n43                cls._finished = Truen45                cls._done = True
44                return None46                return None
n45            if outcome is None:n47            if result is None:
46                cls._finished = True48                cls._done = True
47                return None49                return None
t48            pointer += 1t50            step += 1
49            await asyncio.sleep(0)51            await asyncio.sleep(0)
50        return None52        return None
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op