from __future__ import annotations
from collections import deque
from time import sleep
import typing as T
class Event:
def __init__(self, name: str, action: T.Callable[..., None],
next_event: T.Optional[Event] = None) -> None:
self.name = name
self._action = action
self._next_event = next_event
def execute_action(self) -> None:
self._action(self)
if self._next_event:
event_loop.register_event(self._next_event)
class EventLoop:
def __init__(self) -> None:
self._events: deque[Event] = deque()
def register_event(self, event: Event) -> None:
self._events.append(event)
def run_forever(self) -> None:
print(f"Queue running with {len(self._events)} event")
while True:
try:
event = self._events.popleft()
except IndexError:
continue
event.execute_action()
def knock(event: Event) -> None:
print(event.name)
sleep(1)
def who(event: Event) -> None:
print(event.name)
sleep(1)
if __name__ == "__main__":
event_loop = EventLoop()
replying = Event("Who's there?", who)
knocking = Event("Knock-knock", knock, replying)
for _ in range(2):
event_loop.register_event(knocking)
event_loop.run_forever()
$ python3 event_loop.py
Queue running with 2 event
Knock-knock
Knock-knock
Who’s there?
Who’s there?
import typing as T
import select
from socket import socket, create_server
Data = bytes
Action = T.Union[T.Callable[[socket], None],
T.Tuple[T.Callable[[socket, Data], None], str]]
Mask = int
class EventLoop:
def __init__(self) -> None:
self.writers = {}
self.readers = {}
def register_event(self, source: socket, event: Mask,
action: Action) -> None:
key = source.fileno()
if event & select.POLLIN:
self.readers[key] = (source, event, action)
elif event & select.POLLOUT:
self.writers[key] = (source, event, action)
def unregister_event(self, source: socket) -> None:
key = source.fileno()
if self.readers.get(key):
del self.readers[key]
if self.writers.get(key):
del self.writers[key]
def run_forever(self) -> None:
while True:
readers, writers, _ = select.select(
self.readers, self.writers, [])
for reader in readers:
source, event, action = self.readers.pop(reader)
action(source)
for writer in writers:
source, event, action = self.writers.pop(writer)
action, msg = action
action(source, msg)