F05 — Loop wakeup & external fds
A real application's event loop multiplexes more than window events: timers, sockets, IPC, an async runtime. This demo measures cross-thread wakeup latency and probes whether arbitrary file descriptors (or handles) can join the native loop — and where they cannot.
Requirements
- A second thread posts a user event 10×/second for 30 seconds; the main loop logs
wakeup latency_us=…computed from a monotonic timestamp carried in the event:- Wayland: write to a self-pipe/
eventfdpolled alongside thewl_displayfd (there is no protocol-level user event — that absence is the finding; show the canonicalprepare_read/poll/read_eventsintegration). - X11:
XSendEventwith aClientMessageto self, and the fd alternative below — compare both. - Win32:
PostThreadMessage/PostMessagewith aWM_APP+nmessage. - macOS:
-[NSApplication postEvent:atStart:]of anNSEventTypeApplicationDefinedevent, and aCFRunLoopSourcevariant — compare.
- Wayland: write to a self-pipe/
- Add an arbitrary fd (Linux:
timerfd; macOS: apipeviaCFFileDescriptor/dispatch_source; Win32: a waitable timerHANDLEviaMsgWaitForMultipleObjectsEx) into the same loop and log its ticks interleaved with window events. Where the native loop cannot accept the primitive directly, document the standard workaround and its cost. - Report latency stats (min/median/p99/max) per mechanism at exit.
Instrumentation
wakeup latency_us=… mech=…, fd_tick t=…, plus the mandatory set.
Findings to record
- Latency distributions per mechanism per platform.
- The integration shape a framework must offer (fd-based readiness vs handle-array waits vs run-loop sources) — cross-link the readiness-vs-completion discussion in concepts.
- Thread-safety rules for each injection mechanism (who may call it, from where).
Verification
Wayland/X11: Tier A. Win32: A[wine] (timer-resolution caveats under Wine — note them). macOS: A[ssh]. No genuinely interactive part — this row should be fully agent-verifiable.