Лукьянов Артём Васильевич, 317, Севастопольский филилал TwoWay 11042
Сагура Николай, 392, сев. филиал TwoWay 10440
f1import asynciof1import asyncio
22
3class Portal:3class Portal:
44
5    def __init__(self, parties: int):5    def __init__(self, parties: int):
n6        self._total = partiesn6        self._parties = parties
7        self._phase = 07        self._generation = 0
8        self._count = 08        self._n_waiting = 0
9        self._phase_event = asyncio.Event()9        self._event = asyncio.Event()
10        self._is_broken = False10        self._broken = False
11        self._mutex = asyncio.Lock()11        self._lock = asyncio.Lock()
12        self._last_topic = None12        self._topic = None
13        self._phase_topics_pending = {}13        self._pending_topic = {}
14        self._phase_topics = {}14        self._gen_topic = {}
15        self._task_phase = {}15        self._task_gen = {}
16        self._task_slot = {}16        self._task_index = {}
1717
18    @property18    @property
n19    def parties(self):n19    def parties(self) -> int:
20        return self._total20        return self._parties
2121
22    @property22    @property
n23    def n_waiting(self):n23    def n_waiting(self) -> int:
24        return self._count24        return self._n_waiting
2525
26    @property26    @property
n27    def broken(self):n27    def broken(self) -> bool:
28        return self._is_broken28        return self._broken
2929
30    @property30    @property
31    def topic(self):31    def topic(self):
32        """32        """
n33        Для текущей задачи → её топик фазы.n33        Для задач возвращаем топик их собственного прохода,
34        Для внешнего кода  глобальный последний топик.34        для внешнего кода — последний глобальный топик.
35        """35        """
36        task = asyncio.current_task()36        task = asyncio.current_task()
37        if task is not None:37        if task is not None:
n38            ph = self._task_phase.get(task)n38            gen = self._task_gen.get(task)
39            if ph is not None:39            if gen is not None:
40                t = self._phase_topics.get(ph)40                topic = self._gen_topic.get(gen, None)
41                if t is not None:41                if topic is not None:
42                    return t42                    return topic
43        return self._last_topic43        return self._topic
4444
45    async def wait(self, topic=None):45    async def wait(self, topic=None):
n46        if self._is_broken:n46        if self._broken:
47            raise asyncio.BrokenBarrierError47            raise asyncio.BrokenBarrierError
48        task = asyncio.current_task()48        task = asyncio.current_task()
n49        async with self._mutex:n49        async with self._lock:
50            phase = self._phase50            gen = self._generation
51            self._task_phase[task] = phase51            self._task_gen[task] = gen
52            if topic is not None:52            if topic is not None:
n53                self._phase_topics_pending[phase] = topicn53                self._pending_topic[gen] = topic
54            self._count += 154            self._n_waiting += 1
55            slot = self._total - self._count55            index = self._parties - self._n_waiting
56            self._task_slot[task] = slot56            self._task_index[task] = index
57            my_event = self._phase_event57            my_event = self._event
58            if self._count == self._total:58            if self._n_waiting == self._parties:
59                phase_topic = self._phase_topics_pending.pop(phase, None59                gen_topic = self._pending_topic.pop(gen, None)
>) 
60                self._phase_topics[phase] = phase_topic60                self._gen_topic[gen] = gen_topic
61                self._last_topic = phase_topic61                self._topic = gen_topic
62                self._phase += 162                self._generation += 1
63                self._count = 063                self._n_waiting = 0
64                self._phase_event = asyncio.Event()64                self._event = asyncio.Event()
65                my_event.set()65                my_event.set()
66        await my_event.wait()66        await my_event.wait()
n67        return self._task_slot[task]n67        return self._task_index[task]
6868
69    async def reset(self):69    async def reset(self):
tt70        """
71        Сбрасывает портал в исходное состояние.
72        Предполагается, что вызывается, когда никто не ждёт.
73        """
70        async with self._mutex:74        async with self._lock:
71            self._phase = 075            self._generation = 0
72            self._count = 076            self._n_waiting = 0
73            self._phase_event = asyncio.Event()77            self._event = asyncio.Event()
74            self._is_broken = False78            self._broken = False
75            self._last_topic = None79            self._topic = None
76            self._phase_topics_pending.clear()80            self._pending_topic.clear()
77            self._phase_topics.clear()81            self._gen_topic.clear()
78            self._task_phase.clear()82            self._task_gen.clear()
79            self._task_slot.clear()83            self._task_index.clear()
8084
81    async def __aenter__(self):85    async def __aenter__(self):
82        return await self.wait()86        return await self.wait()
8387
84    async def __aexit__(self, exc_type, exc, tb):88    async def __aexit__(self, exc_type, exc, tb):
85        return False89        return False
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op