Зыков Валерий Павлович, 517 GroupWork 11251
Морозов Иван Дмитриевич, 517 GroupWork 11254
f1import asynciof1import asyncio
2from collections import deque2from collections import deque
33
4class Loop:4class Loop:
n5    """Параметрический декоратор для корутин с синхронизацией выполненияn
>""" 
6    _coros = []
7    _args_kwargs = []5    _tasks = []
6    _params = []
8    _current = 07    _cursor = 0
9    _done = False
10    _scheduled = False8    _finished = False
9    _active = False
1110
12    def __init__(self):11    def __init__(self):
n13        self.index = len(Loop._coros)n12        self._id = len(Loop._tasks)
13        Loop._tasks.append(None)
14        Loop._coros.append(None)14        Loop._params.append(None)
15        Loop._args_kwargs.append(None)
1615
n17    def __call__(self, coro):n16    def __call__(self, fn):
18        Loop._coros[self.index] = coro17        Loop._tasks[self._id] = fn
1918
n20        async def wrapper(*args, **kwargs):n19        async def launcher(*args, **kwargs):
21            Loop._args_kwargs[self.index] = (args, kwargs)20            Loop._params[self._id] = (args, kwargs)
22            if not Loop._scheduled:21            if not Loop._active:
23                Loop._scheduled = True22                Loop._active = True
24                return await Loop._run_scheduler()23                return await Loop._run_scheduler()
25            return None24            return None
n26        return wrappern25        return launcher
2726
28    @classmethod27    @classmethod
29    async def _run_scheduler(cls):28    async def _run_scheduler(cls):
n30        """Планировщик, который выполняет все корутины по очереди"""n
31        step = 029        pointer = 0
32        total_coros = len(cls._coros)30        count = len(cls._tasks)
33        while not cls._done:31        while not cls._finished:
34            idx = step % total_coros32            slot = pointer % count
35            coro = cls._coros[idx]33            task = cls._tasks[slot]
36            args_kwargs = cls._args_kwargs[idx]34            payload = cls._params[slot]
37            if coro is None or args_kwargs is None:35            if task is None or payload is None:
38                step += 136                pointer += 1
39                await asyncio.sleep(0)37                await asyncio.sleep(0)
40                continue38                continue
n41            args, kwargs = args_kwargsn39            args, kwargs = payload
42            try:40            try:
n43                result = await coro(*args, **kwargs)n41                outcome = await task(*args, **kwargs)
44            except asyncio.CancelledError:42            except asyncio.CancelledError:
n45                cls._done = Truen43                cls._finished = True
46                return None44                return None
n47            if result is None:n45            if outcome is None:
48                cls._done = True46                cls._finished = True
49                return None47                return None
t50            step += 1t48            pointer += 1
51            await asyncio.sleep(0)49            await asyncio.sleep(0)
52        return None50        return None
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op