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)