Polite Ping-Pong: The State Machine Pattern ============================================ Extends the basic ping-pong into a proper state machine with dispatch tables. Alice and Bob have a polite exchange: ping, pong, thank you, you're welcome. Found in ``examples/event-based/politePingPong/``. This is still purely classical, but introduces the **state machine pattern** that all subsequent quantum examples will use. Alice's state diagram --------------------- :: (connect) │ send "ping" ▼ WAITING_PONG │ recv "pong" → send "thank you" ▼ WAITING_YOURE_WELCOME │ recv "you're welcome" ▼ DONE Alice's dispatch table ---------------------- :: ALICE_DISPATCH = { (STATE_WAITING_PONG, "pong"): handle_pong, (STATE_WAITING_YOURE_WELCOME, "you're welcome"): handle_youre_welcome, } Each handler is a focused function that performs one action and returns the next state:: async def handle_pong(writer: StreamWriter) -> str: reply = "thank you" writer.write(reply.encode("utf-8")) await writer.drain() return STATE_WAITING_YOURE_WELCOME The event loop -------------- The event loop is generic — it works for any protocol by just changing the dispatch table and initial state:: async def run_alice(reader: StreamReader, writer: StreamWriter): # Initial action (before the loop) writer.write(b"ping") await writer.drain() state = STATE_WAITING_PONG while state != STATE_DONE: data = await reader.read(255) if not data: break msg = data.decode("utf-8") handler = ALICE_DISPATCH.get((state, msg)) if handler is None: print(f"no transition for '{msg}' — ignoring.") continue state = await handler(writer) Key concepts ------------ - **Dispatch table = state machine**: the ``(state, message) → handler`` mapping *is* the protocol definition. Every valid transition is listed; anything not listed is automatically rejected. - **Handlers are independent**: each handler only knows about its own transition, making the code modular and easy to extend. - **The event loop is reusable**: the same loop structure works for every example that follows. Bob's side ---------- Bob uses the same pattern with his own states (``WAITING_PING``, ``WAITING_THANKS``, ``DONE``) and dispatch table. See ``politeBob.py`` for the full code. Running ------- :: cd examples/event-based/politePingPong bash run.sh