// F03 — modal-loop survival, X11 edition (../../../features/f03-modal-loop.md).
// Derived from the X11 scaffold (../scaffold/app.d) and the F02 demo
// (../f02-resize/app.d). On Win32, interactive resize/move traps the thread in
// a system modal loop (WM_ENTERSIZEMOVE) and the message pump stops being
// yours; the F03 spec asks each platform to prove animation survives that.
// X11's answer is that THERE IS NO MODAL LOOP TO SURVIVE: resize — self,
// external-client, or WM-mediated — is just more events in the same queue, and
// nothing ever takes the thread away from the app's own poll(2) loop. This
// demo makes that absence measurable:
//
// * a ~2 Hz full-window color cycle, ticked by a TIMERFD polled alongside
// the X connection fd — the animation clock is the app's own, exactly the
// loop shape a framework owns; X11 never re-enters or blocks it;
// * a `tick t=… n=… phase=… presented=0|1 gap_us=…` line per animation
// frame, where gap_us is the delta to the previous tick — the modal-loop
// symptom (animation freeze) would show as an unbounded gap;
// * three instrumented phases: `calm` (baseline cadence), `self` (a resize
// storm from the demo's own connection: XResizeWindow every other tick,
// 25 requests), `ext` (the same storm from a SECOND Display* connection —
// what a WM or `xdotool` does), then a drain; per-phase
// `gap_summary phase=… ticks=… resizes=… max_gap_us=…` lines at exit;
// * every ConfigureNotify still triggers the naive realloc-the-SHM-segment
// response from F02 — the worst-case per-resize work — and the tick
// cadence must hold anyway;
// * protocol errors via XSetErrorHandler; the run must end errors=0.
//
// Run it once on bare Xvfb and once with icewm inside the same Xvfb: under
// the WM every resize becomes a ConfigureRequest the WM mediates (see the
// F02 findings) — the closest X11 gets to "someone else is driving" — and the
// ticks must still flow. True interactive border-drag needs a human and a
// real session: Tier C, queued in ../../../manual-run-queue.md.
//
// WSI_AUTO_EXIT=1 bounds the run (~2.6 s, 156 ticks); otherwise it runs until
// WM_DELETE_WINDOW, ticking forever. Headless-safe: no display prints `SKIP:`
// and exits 0. Findings: ../../f03-modal-loop.md.
module (module) appapp;
import (module) cc; // ImportC: Xlib + Xutil + Xatom + XShm + sys/ipc + sys/shm + timerfd + poll
import (module) instrumentinstrument;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.configD compatible types that correspond to various basic types in associated
C and C++ compilers.
Source
core/stdc/config.d
config : c_long, c_ulong;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stdioD header file for C99 <stdio.h>
pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h
Source
core/stdc/stdio.d
stdio : (alias) app.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stdlibD header file for C99.
pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h
Source
core/stdc/stdlib.d
stdlib : (alias) app.getenv = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(module) core.sys.posix.unistdD header file for POSIX.
unistd : (alias) app.read = long core.sys.posix.unistd.read(int, void*, ulong) nothrow @nogcread;
// Constants Xlib/glibc expose only as macros (not ImportC-able); re-declared
// per the ImportC guide, same as the scaffold.
enum : c_long
{
(enum value) app.KeyPressMask = 1LKeyPressMask = 1L << 0,
(enum value) app.ExposureMask = 32768LExposureMask = 1L << 15,
(enum value) app.StructureNotifyMask = 131072LStructureNotifyMask = 1L << 17,
}
enum // XEvent.type discriminators
{
(enum value) app.KeyPress = 2KeyPress = 2,
(enum value) app.Expose = 12Expose = 12,
(enum value) app.MapNotify = 19MapNotify = 19,
(enum value) app.ReparentNotify = 21ReparentNotify = 21,
(enum value) app.ConfigureNotify = 22ConfigureNotify = 22,
(enum value) app.ClientMessage = 33ClientMessage = 33,
}
enum (constant) int app.ZPixmap = 2ZPixmap = 2;
enum (constant) int app.ShmCompletion = 0ShmCompletion = 0; // offset inside MIT-SHM's allocated event range
enum (constant) int app.False = 0False = 0;
enum (constant) int app.True = 1True = 1;
enum (constant) int app.POLLIN = 1POLLIN = 0x001;
enum (constant) int app.IPC_PRIVATE = 0IPC_PRIVATE = 0;
enum (constant) int app.IPC_CREAT = 512IPC_CREAT = 0x200; // 01000 octal
enum (constant) int app.IPC_RMID = 0IPC_RMID = 0;
enum (constant) int app.CLOCK_MONOTONIC = 1CLOCK_MONOTONIC = 1;
// ---------------------------------------------------------------------------
// Protocol-error accounting, as in F02: Xlib reports errors asynchronously.
__gshared int (__gshared global) int app.g_xErrorsg_xErrors = 0;
extern (C) int app.onXErroronXError(Display* (parameter) Display* dpydpy, XErrorEvent* e) @nogc nothrow
{
char[128] _error_ texttext = 0;
XGetErrorText(dpy, e.error_code, text.text.ptrptr, text.length);
emitf("x_error", "code=%d request=%d.%d resource=0x%lx text=%s",
e.error_code, e.request_code, e.minor_code, e.resourceid, text.text.ptrptr);
++g_xErrors;
return 0;
}
// ---------------------------------------------------------------------------
// Backbuffer: MIT-SHM XImage with plain-XPutImage fallback (as the scaffold).
struct (struct) app.BackbufferBackbuffer
{
XImage* (field) _error_ app.Backbuffer.ximgximg;
XShmSegmentInfo (field) _error_ app.Backbuffer.shminfoshminfo;
bool (field) bool app.Backbuffer.usingShmusingShm;
int (field) int app.Backbuffer.widthwidth, (field) int app.Backbuffer.heightheight;
}
(struct) app.BackbufferBackbuffer app.createBackbuffercreateBackbuffer(Display* (parameter) Display* dpydpy, Visual* (parameter) Visual* visualvisual, int (parameter) int depthdepth,
int (parameter) int ww, int (parameter) int hh, bool wantShm) @nogc nothrow
{
(unresolved type) BackbufferBackbuffer _error_ bb;
b.b.widthwidth = w;
b.b.heightheight = h;
if (wantShm)
{
b.b.ximgximg = XShmCreateImage(dpy, visual, cast(uint) depth, ZPixmap,
null, &b.b.shminfoshminfo, cast(uint) w, cast(uint) h);
if (b.b.ximgximg !is null)
{
const _error_ nbytesnbytes = cast(size_t)(b.b.ximgximg.bytes_per_line * b.b.ximgximg.b.ximg.heightheight);
b.b.shminfoshminfo.shmid = shmget(IPC_PRIVATE, nbytes, IPC_CREAT | 0x180 /* 0600 */ );
if (b.b.shminfoshminfo.shmid >= 0)
{
b.b.shminfoshminfo.shmaddr = cast(char*) shmat(b.b.shminfoshminfo.shmid, null, 0);
if (b.b.shminfoshminfo.shmaddr !is cast(char*)-1)
{
b.b.ximgximg.b.ximg.datadata = b.b.shminfoshminfo.shmaddr;
b.b.shminfoshminfo.readOnly = False;
XShmAttach(dpy, &b.b.shminfoshminfo);
XSync(dpy, False); // server attached before ...
shmctl(b.b.shminfoshminfo.shmid, IPC_RMID, null); // ... mark-for-delete
b.b.usingShmusingShm = true;
return b;
}
shmctl(b.b.shminfoshminfo.shmid, IPC_RMID, null);
}
b.b.ximgximg.f.destroy_image(b.b.ximgximg); // XDestroyImage is a macro
b.b.ximgximg = null;
}
emit("step name=shm_fallback reason=alloc_or_attach_failed");
}
import core.stdc.stdlib : malloc;
auto _error_ datadata = cast(char*) malloc(cast(size_t) w * h * 4);
b.b.ximgximg = XCreateImage(dpy, visual, cast(uint) depth, ZPixmap, 0, data,
cast(uint) w, cast(uint) h, 32, 0);
b.b.usingShmusingShm = false;
return b;
}
void app.destroyBackbufferdestroyBackbuffer(Display* (parameter) Display* dpydpy, ref (struct) app.BackbufferBackbuffer (parameter) Backbuffer bb) @nogc nothrow
{
if (b.b.ximgximg is null)
return;
if (b.b.usingShmusingShm)
{
XSync(dpy, False); // let any in-flight XShmPutImage finish reading
XShmDetach(dpy, &b.b.shminfoshminfo);
}
b.b.ximgximg.f.destroy_image(b.b.ximgximg);
if (b.b.usingShmusingShm)
shmdt(b.b.shminfoshminfo.shmaddr);
b.b.ximgximg = null;
}
/// Full-window solid fill from an 8-bit hue phase: three 120°-offset triangle
/// waves (R/G/B). Phase advances 8 steps per ~16 ms tick — a full cycle every
/// 32 ticks, i.e. the spec's ~2 Hz color cycle at the 62.5 Hz tick rate.
void app.fillColorCycleFull-window solid fill from an 8-bit hue phase: three 120°-offset triangle
waves (R/G/B). Phase advances 8 steps per ~16 ms tick — a full cycle every
32 ticks, i.e. the spec's ~2 Hz color cycle at the 62.5 Hz tick rate.
fillColorCycle(XImage* (parameter) XImage* ximgximg, int phase) @nogc nothrow
{
static uint uint tri(int p) nothrow @nogctri(int (parameter) int pp) @nogc nothrow // triangle wave, period 256, 0..255
{
const _error_ vv = p & 0xff;
return cast(uint)(v < 128 ? v * 2 : (255 - v) * 2);
}
const _error_ rgbrgb = (tri(phase) << 16) | (tri(phase + 85) << 8) | tri(phase + 170);
const _error_ ww = ximg.ximg.widthwidth, _error_ hh = ximg.ximg.heightheight;
if (ximg.bits_per_pixel != 32)
return;
foreach ((parameter) yy; 0 .. h)
{
auto _error_ rowrow = cast(uint*)(ximg.ximg.datadata + y * ximg.bytes_per_line);
row[0 .. w] = rgb;
}
}
int int D main()main()
{
void instrument.initInstrument(const(char)* demoName) nothrow @nogcNames the demo, starts the monotonic clock, and emits init_start.
Call this first, before any platform API call.
initInstrument("f03_x11");
const (local variable) const(char*) envAutoenvAuto = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv("WSI_AUTO_EXIT");
const (local variable) const(bool) autoExitautoExit = (local variable) const(char*) envAutoenvAuto !is null && (local variable) const(char*) envAutoenvAuto[0] == '1';
XSetErrorHandler(&onXError);
Display* (local variable) _error_ dpydpy = XOpenDisplay(null);
if (dpy is null)
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("SKIP: no X11 display (XOpenDisplay returned null)\n");
return 0;
}
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XOpenDisplay fd=%d", XConnectionNumber(dpy));
const (local variable) const(_error_) screenscreen = XDefaultScreen(dpy);
const (local variable) const(_error_) rootroot = XRootWindow(dpy, screen);
Visual* (local variable) _error_ visualvisual = XDefaultVisual(dpy, screen);
const (local variable) const(_error_) depthdepth = XDefaultDepth(dpy, screen);
bool (local variable) bool haveShmhaveShm = XShmQueryExtension(dpy) != 0 && char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv("WSI_NO_SHM") is null;
int (local variable) int shmCompletionTypeshmCompletionType = (local variable) bool haveShmhaveShm ? XShmGetEventBase(dpy) + ShmCompletion : -1;
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XShmQueryExtension using_shm=%d", cast(int) (local variable) bool haveShmhaveShm);
int (local variable) int widthwidth = 480, (local variable) int heightheight = 320;
Window (local variable) _error_ winwin = XCreateSimpleWindow(dpy, root, 0, 0, width, height, 1,
XBlackPixel(dpy, screen), XWhitePixel(dpy, screen));
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XCreateSimpleWindow xid=0x%lx", win);
XStoreName(dpy, win, "Sparkles · X11 F03");
Atom (local variable) _error_ wmDeletewmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, win, &wmDelete, 1);
XSelectInput(dpy, win, ExposureMask | KeyPressMask | StructureNotifyMask);
XMapWindow(dpy, win);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("window_created", "xid=0x%lx size=%dx%d", win, (local variable) int widthwidth, (local variable) int heightheight);
GC (local variable) _error_ gcgc = XDefaultGC(dpy, screen);
auto (local variable) _error_ bufbuf = createBackbuffer(dpy, visual, depth, width, height, haveShm);
// -- The animation heartbeat: a timerfd at 16 ms (62.5 Hz) ----------------
// The clock the app OWNS — F03's point is that on X11 nothing the window
// system does can stop this fd from firing or the loop from reading it.
const (local variable) const(_error_) tfdtfd = timerfd_create(CLOCK_MONOTONIC, 0);
itimerspec (local variable) _error_ itsits;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 16_000_000; // 16 ms
its.it_value = its.it_interval;
timerfd_settime(tfd, 0, &its, null);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=timerfd_create fd=%d interval_ms=16", tfd);
Display* (local variable) _error_ dpy2dpy2 = null; // the "outside world" connection for the ext phase
scope (exit)
{
if (dpy2 !is null)
XCloseDisplay(dpy2);
destroyBackbuffer(dpy, buf);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
}
// -- Phase plan (auto-exit mode) ------------------------------------------
// calm ticks 1..31 no resizes (baseline tick cadence)
// self ticks 32..81 XResizeWindow on dpy every other tick (25 reqs)
// ext ticks 82..131 XResizeWindow on dpy2 every other tick (25 reqs)
// drain ticks 132..156 no resizes (recovery), then exit
static immutable int[2][6] (immutable global) immutable(int[2][6]) app.main.sizessizes = [
[640, 400], [320, 240], [800, 520], [400, 300], [720, 480], [360, 260],
];
enum (constant) int app.main.calmEnd = 31calmEnd = 31, (constant) int app.main.selfEnd = 81selfEnd = 81, (constant) int app.main.extEnd = 131extEnd = 131, (constant) int app.main.lastTick = 156lastTick = 156;
static immutable (alias) object.string = stringstring[4] (immutable global) immutable(string[4]) app.main.phaseNamesphaseNames = ["calm", "self", "ext", "drain"];
long[4] (local variable) long[4] maxGapmaxGap = 0;
int[4] (local variable) int[4] phaseTicksphaseTicks = 0, (local variable) int[4] phaseResizesphaseResizes = 0;
const (local variable) const(_error_) xfdxfd = XConnectionNumber(dpy);
bool (local variable) bool runningrunning = true, (local variable) bool awaitingCompletionawaitingCompletion = false, (local variable) bool sawFirstPixelsawFirstPixel = false;
int (local variable) int ticksticks = 0, (local variable) int colorPhasecolorPhase = 0, (local variable) int sizeIdxsizeIdx = 0;
long (local variable) long lastTickUslastTickUs = 0;
while ((local variable) bool runningrunning)
{
while (XPending(dpy) > 0) // XPending also flushes the output buffer
{
XEvent (local variable) _error_ evev;
XNextEvent(dpy, &ev);
switch (ev.type)
{
case MapNotify:
emitf("map_notify", "serial=%lu", ev.xany.serial);
break;
case ReparentNotify: // a WM adopted us (never seen on bare Xvfb)
emitf("reparent_notify", "parent=0x%lx", ev.xreparent.parent);
break;
case ConfigureNotify:
const _error_ cwcw = ev.xconfigure.ev.xconfigure.widthwidth, _error_ chch = ev.xconfigure.ev.xconfigure.heightheight;
if (cw != width || ch != height)
{
width = cw;
height = ch;
emitf("resize", "size=%dx%d scale=1", width, height);
destroyBackbuffer(dpy, buf);
buf = createBackbuffer(dpy, visual, depth, width, height, haveShm);
emitf("buffer_realloc", "size=%dx%d shm=%d", width, height,
cast(int) buf.buf.usingShmusingShm);
}
break;
case Expose:
if (ev.xexpose.count == 0 && !sawFirstPixel)
{
// Present the very first frame eagerly so the run is
// anchored; afterwards only ticks present.
fillColorCycle(buf.buf.ximgximg, colorPhase);
if (buf.buf.usingShmusingShm)
{
XShmPutImage(dpy, win, gc, buf.buf.ximgximg, 0, 0, 0, 0,
cast(uint) buf.buf.widthwidth, cast(uint) buf.buf.heightheight, True);
XFlush(dpy);
awaitingCompletion = true;
}
else
{
XPutImage(dpy, win, gc, buf.buf.ximgximg, 0, 0, 0, 0,
cast(uint) buf.buf.widthwidth, cast(uint) buf.buf.heightheight);
XSync(dpy, False);
}
sawFirstPixel = true;
emit("first_pixel_presented");
}
break;
case ClientMessage:
if (cast(Atom) ev.xclient.ev.xclient.datadata.l[0] == wmDelete)
{
emit("close_requested via=WM_DELETE_WINDOW");
running = false;
}
break;
case KeyPress:
emit("close_requested via=KeyPress");
running = false;
break;
default:
if (buf.buf.usingShmusingShm && ev.type == shmCompletionType)
awaitingCompletion = false;
break;
}
}
// -- Wait for either X traffic or the next animation tick -------------
pollfd[2] (local variable) _error_ pfdspfds;
pfds[0].fd = xfd;
pfds[0].events = POLLIN;
pfds[0].revents = 0;
pfds[1].fd = tfd;
pfds[1].events = POLLIN;
pfds[1].revents = 0;
poll(pfds.pfds.ptrptr, 2, -1);
if (!(pfds[1].revents & POLLIN) || !(local variable) bool sawFirstPixelsawFirstPixel)
continue; // X traffic only — loop back to drain it
ulong (local variable) ulong expirationsexpirations;
long core.sys.posix.unistd.read(int, void*, ulong) nothrow @nogcread(tfd, &(local variable) ulong expirationsexpirations, (local variable) ulong expirationsexpirations.(constant) ulong ulong.sizeof = 8LUsizeof);
// -- One animation tick ------------------------------------------------
++(local variable) int ticksticks;
(local variable) int colorPhasecolorPhase += 8; // 8/256 per 16 ms tick ≈ 2 full cycles per second
const (local variable) const(int) phaseIdxphaseIdx = (local variable) int ticksticks <= (constant) int app.main.calmEnd = 31calmEnd ? 0 : (local variable) int ticksticks <= (constant) int app.main.selfEnd = 81selfEnd ? 1
: (local variable) int ticksticks <= (constant) int app.main.extEnd = 131extEnd ? 2 : 3;
// The storm driver: during `self`/`ext`, fire a resize every other
// tick while the animation must keep its cadence.
if ((local variable) const(bool) autoExitautoExit && ((local variable) const(int) phaseIdxphaseIdx == 1 || (local variable) const(int) phaseIdxphaseIdx == 2) && ((local variable) int ticksticks & 1) == 0)
{
const (local variable) immutable(int[2]) ss = (immutable global) immutable(int[2][6]) app.main.sizessizes[(local variable) int sizeIdxsizeIdx % $];
++(local variable) int sizeIdxsizeIdx;
if ((local variable) const(int) phaseIdxphaseIdx == 1)
{
XResizeWindow(dpy, win, cast(uint) s[0], cast(uint) s[1]);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XResizeWindow conn=self n=%d size=%dx%d",
(local variable) int[4] phaseResizesphaseResizes[1] + 1, (local variable) immutable(int[2]) ss[0], (local variable) immutable(int[2]) ss[1]);
}
else
{
if (dpy2 is null)
{
dpy2 = XOpenDisplay(null);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XOpenDisplay conn=external fd=%d",
dpy2 !is null ? XConnectionNumber(dpy2) : -1);
}
if (dpy2 !is null)
{
XResizeWindow(dpy2, win, cast(uint) s[0], cast(uint) s[1]);
XSync(dpy2, False);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XResizeWindow conn=external n=%d size=%dx%d",
(local variable) int[4] phaseResizesphaseResizes[2] + 1, (local variable) immutable(int[2]) ss[0], (local variable) immutable(int[2]) ss[1]);
}
}
++(local variable) int[4] phaseResizesphaseResizes[(local variable) const(int) phaseIdxphaseIdx];
}
// Present this tick's color. With MIT-SHM the segment must not be
// rewritten while the server still reads it; a tick that lands inside
// that sub-millisecond window is logged presented=0 (the heartbeat
// still beat — only the pixels waited one frame).
bool (local variable) bool presentedpresented = false;
if (!(local variable) bool awaitingCompletionawaitingCompletion && buf.(field) _error_ buf.ximgximg !is null)
{
fillColorCycle(buf.buf.ximgximg, colorPhase);
if (buf.(field) _error_ buf.usingShmusingShm)
{
XShmPutImage(dpy, win, gc, buf.buf.ximgximg, 0, 0, 0, 0,
cast(uint) buf.buf.widthwidth, cast(uint) buf.buf.heightheight, True);
XFlush(dpy);
(local variable) bool awaitingCompletionawaitingCompletion = true;
}
else
{
XPutImage(dpy, win, gc, buf.buf.ximgximg, 0, 0, 0, 0,
cast(uint) buf.buf.widthwidth, cast(uint) buf.buf.heightheight);
XSync(dpy, False);
}
(local variable) bool presentedpresented = true;
}
const (local variable) const(long) nownow = long instrument.nowUs() nothrow @nogcMicroseconds elapsed since initInstrument.
nowUs();
const (local variable) const(long) gapgap = (local variable) long lastTickUslastTickUs == 0 ? 0 : (local variable) const(long) nownow - (local variable) long lastTickUslastTickUs;
(local variable) long lastTickUslastTickUs = (local variable) const(long) nownow;
++(local variable) int[4] phaseTicksphaseTicks[(local variable) const(int) phaseIdxphaseIdx];
if ((local variable) const(long) gapgap > (local variable) long[4] maxGapmaxGap[(local variable) const(int) phaseIdxphaseIdx])
(local variable) long[4] maxGapmaxGap[(local variable) const(int) phaseIdxphaseIdx] = (local variable) const(long) gapgap;
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("tick", "t=%lld n=%d phase=%s presented=%d gap_us=%lld",
(local variable) const(long) nownow, (local variable) int ticksticks, (immutable global) immutable(string[4]) app.main.phaseNamesphaseNames[(local variable) const(int) phaseIdxphaseIdx].(field) immutable(char)* immutable(string).ptrptr, cast(int) (local variable) bool presentedpresented, (local variable) const(long) gapgap);
if ((local variable) const(bool) autoExitautoExit && (local variable) int ticksticks >= (constant) int app.main.lastTick = 156lastTick)
break;
}
// -- The F03 verdict: per-phase tick cadence under resize fire -------------
foreach ((parameter) ulong ii, (parameter) immutable(string) namename; (immutable global) immutable(string[4]) app.main.phaseNamesphaseNames)
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("gap_summary", "phase=%s ticks=%d resizes=%d max_gap_us=%lld",
(local variable) immutable(string) namename.(field) immutable(char)* immutable(string).ptrptr, (local variable) int[4] phaseTicksphaseTicks[(local variable) ulong ii], (local variable) int[4] phaseResizesphaseResizes[(local variable) ulong ii], (local variable) long[4] maxGapmaxGap[(local variable) ulong ii]);
const (local variable) const(long) stormMaxstormMax = (local variable) long[4] maxGapmaxGap[1] > (local variable) long[4] maxGapmaxGap[2] ? (local variable) long[4] maxGapmaxGap[1] : (local variable) long[4] maxGapmaxGap[2];
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("finding", "modal_loop=absent max_gap_storm_us=%lld errors=%d",
(local variable) const(long) stormMaxstormMax, (__gshared global) int app.g_xErrorsg_xErrors);
void instrument.emit(scope const(char)* kind) nothrow @nogcEmit an event with no key=value payload.
emit("teardown");
return (__gshared global) int app.g_xErrorsg_xErrors == 0 ? 0 : 1;
}