Skip to content

Instantly share code, notes, and snippets.

@Mic92
Last active March 12, 2026 19:21
Show Gist options
  • Select an option

  • Save Mic92/2feae981c38e80bfaa18806fda7a1321 to your computer and use it in GitHub Desktop.

Select an option

Save Mic92/2feae981c38e80bfaa18806fda7a1321 to your computer and use it in GitHub Desktop.
Visualization of commit 47d2d18: Make computeClosure async (Nix)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>computeClosure async — State Machine & Sequence Diagrams</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; background: #0d1117; color: #c9d1d9; padding: 32px 48px; }
h1 { color: #58a6ff; font-size: 1.4em; margin-bottom: 4px; }
.subtitle { color: #8b949e; font-size: 0.85em; margin-bottom: 32px; font-family: 'JetBrains Mono', monospace; }
h2 { color: #58a6ff; font-size: 1.15em; margin-bottom: 16px; }
section { margin-bottom: 48px; }
.diagram-box {
background: #161b22; border: 1px solid #30363d; border-radius: 12px;
padding: 24px; overflow-x: auto;
}
svg text { font-family: 'Segoe UI', system-ui, sans-serif; }
code { font-family: 'JetBrains Mono', monospace; font-size: 0.85em; color: #79c0ff; }
</style>
</head>
<body>
<h1>libutil: Make computeClosure async</h1>
<div class="subtitle">47d2d1815f — State Machine & Sequence Diagrams</div>
<!-- ============================================================ -->
<!-- STATE MACHINE DIAGRAM -->
<!-- ============================================================ -->
<section>
<h2>🧵 Async State Machine (<code>closure.hh</code> — State struct)</h2>
<div class="diagram-box">
<svg viewBox="0 0 1060 520" width="100%" height="520" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arr" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#58a6ff"/>
</marker>
<marker id="arr-green" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#3fb950"/>
</marker>
<marker id="arr-yellow" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#d29922"/>
</marker>
<marker id="arr-red" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#f85149"/>
</marker>
<marker id="arr-purple" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#d2a8ff"/>
</marker>
<marker id="arr-gray" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#484f58"/>
</marker>
</defs>
<!-- ===== IDLE / START ===== -->
<circle cx="60" cy="110" r="28" fill="none" stroke="#8b949e" stroke-width="2"/>
<circle cx="60" cy="110" r="24" fill="#161b22" stroke="#8b949e" stroke-width="1"/>
<text x="60" y="114" text-anchor="middle" fill="#8b949e" font-size="11" font-weight="600">START</text>
<!-- Arrow: START → enqueue -->
<line x1="88" y1="110" x2="148" y2="110" stroke="#8b949e" stroke-width="1.5" marker-end="url(#arr-gray)"/>
<text x="118" y="102" text-anchor="middle" fill="#8b949e" font-size="9">post(startElts)</text>
<!-- ===== enqueue(elt) ===== -->
<rect x="150" y="78" width="170" height="64" rx="10" fill="#0f1d0f" stroke="#3fb950" stroke-width="1.5"/>
<text x="235" y="102" text-anchor="middle" fill="#3fb950" font-size="12" font-weight="700">enqueue(elt)</text>
<text x="235" y="118" text-anchor="middle" fill="#8b949e" font-size="9.5">res.insert(elt)</text>
<text x="235" y="131" text-anchor="middle" fill="#8b949e" font-size="9.5">pending++</text>
<!-- Guard: already seen? -->
<rect x="160" y="12" width="150" height="36" rx="8" fill="#1c1012" stroke="#f8514966" stroke-width="1"/>
<text x="235" y="34" text-anchor="middle" fill="#f85149" font-size="10">already in res → skip</text>
<path d="M 235 78 L 235 50" fill="none" stroke="#f8514966" stroke-width="1" marker-end="url(#arr-red)" stroke-dasharray="4,3"/>
<!-- ===== Decision diamond: inFlight < 64? ===== -->
<polygon points="460,110 530,70 600,110 530,150" fill="#0d1117" stroke="#58a6ff" stroke-width="1.5"/>
<text x="530" y="107" text-anchor="middle" fill="#58a6ff" font-size="10" font-weight="600">inFlight</text>
<text x="530" y="120" text-anchor="middle" fill="#58a6ff" font-size="10" font-weight="600">&lt; 64 ?</text>
<!-- enqueue → decision -->
<line x1="320" y1="110" x2="458" y2="110" stroke="#3fb950" stroke-width="1.5" marker-end="url(#arr-green)"/>
<!-- ===== spawnWorker(elt) ===== -->
<rect x="640" y="30" width="180" height="64" rx="10" fill="#0f1d0f" stroke="#58a6ff" stroke-width="1.5"/>
<text x="730" y="54" text-anchor="middle" fill="#58a6ff" font-size="12" font-weight="700">spawnWorker(elt)</text>
<text x="730" y="70" text-anchor="middle" fill="#8b949e" font-size="9.5">inFlight++</text>
<text x="730" y="83" text-anchor="middle" fill="#8b949e" font-size="9.5">co_spawn on strand</text>
<!-- decision → spawnWorker (yes) -->
<path d="M 565 85 Q 590 62 638 62" fill="none" stroke="#58a6ff" stroke-width="1.5" marker-end="url(#arr)"/>
<text x="595" y="58" fill="#3fb950" font-size="9" font-weight="600">yes</text>
<!-- ===== todo.push(elt) ===== -->
<rect x="640" y="160" width="180" height="56" rx="10" fill="#161b22" stroke="#d29922" stroke-width="1.5"/>
<text x="730" y="184" text-anchor="middle" fill="#d29922" font-size="12" font-weight="700">todo.push(elt)</text>
<text x="730" y="200" text-anchor="middle" fill="#8b949e" font-size="9.5">queued for later</text>
<!-- decision → todo (no) -->
<path d="M 565 135 Q 590 168 638 188" fill="none" stroke="#d29922" stroke-width="1.5" marker-end="url(#arr-yellow)"/>
<text x="595" y="162" fill="#f85149" font-size="9" font-weight="600">no</text>
<!-- ===== co_await getEdges(elt) ===== -->
<rect x="640" y="270" width="180" height="56" rx="10" fill="#0f1d0f" stroke="#d2a8ff" stroke-width="1.5"/>
<text x="730" y="293" text-anchor="middle" fill="#d2a8ff" font-size="11" font-weight="700">co_await getEdges</text>
<text x="730" y="310" text-anchor="middle" fill="#8b949e" font-size="9.5">network I/O (suspended)</text>
<!-- spawnWorker → co_await -->
<line x1="730" y1="94" x2="730" y2="268" stroke="#58a6ff" stroke-width="1.5" marker-end="url(#arr)"/>
<text x="742" y="190" fill="#8b949e" font-size="9">coroutine body</text>
<!-- ===== onWorkDone() ===== -->
<rect x="640" y="380" width="180" height="64" rx="10" fill="#0f1d0f" stroke="#d2a8ff" stroke-width="1.5"/>
<text x="730" y="404" text-anchor="middle" fill="#d2a8ff" font-size="12" font-weight="700">onWorkDone()</text>
<text x="730" y="420" text-anchor="middle" fill="#8b949e" font-size="9.5">inFlight--</text>
<text x="730" y="433" text-anchor="middle" fill="#8b949e" font-size="9.5">pending--</text>
<!-- co_await → enqueue new edges (results arrive) -->
<line x1="730" y1="326" x2="730" y2="344" stroke="#d2a8ff" stroke-width="1.5"/>
<!-- enqueue new edges label + loop back -->
<path d="M 640 298 Q 460 298 300 190 Q 235 158 235 144" fill="none" stroke="#3fb95088" stroke-width="1.5" marker-end="url(#arr-green)" stroke-dasharray="5,3"/>
<text x="400" y="260" fill="#3fb950" font-size="9.5" font-weight="600">enqueue(new edges)</text>
<!-- small box: try/catch -->
<rect x="520" y="330" width="100" height="30" rx="6" fill="#1c1012" stroke="#f8514966" stroke-width="1"/>
<text x="570" y="349" text-anchor="middle" fill="#f85149" font-size="9">catch → complete(ex)</text>
<path d="M 640 310 Q 620 330 622 340" fill="none" stroke="#f8514966" stroke-width="1" stroke-dasharray="3,2"/>
<!-- co_await → onWorkDone -->
<text x="742" y="358" fill="#8b949e" font-size="9">then</text>
<line x1="730" y1="344" x2="730" y2="378" stroke="#d2a8ff" stroke-width="1.5" marker-end="url(#arr-purple)"/>
<!-- ===== Decision: todo empty? ===== -->
<polygon points="440,412 510,380 580,412 510,444" fill="#0d1117" stroke="#d29922" stroke-width="1.5"/>
<text x="510" y="408" text-anchor="middle" fill="#d29922" font-size="9.5" font-weight="600">todo</text>
<text x="510" y="422" text-anchor="middle" fill="#d29922" font-size="9.5" font-weight="600">empty?</text>
<!-- onWorkDone → decision -->
<line x1="640" y1="412" x2="582" y2="412" stroke="#d29922" stroke-width="1.5" marker-end="url(#arr-yellow)"/>
<!-- decision → spawnWorker (todo not empty: pop and spawn) -->
<path d="M 510 380 Q 510 62 638 62" fill="none" stroke="#d29922" stroke-width="1.5" marker-end="url(#arr-yellow)" stroke-dasharray="5,3"/>
<text x="496" y="210" fill="#d29922" font-size="9.5" font-weight="600" transform="rotate(-90 496 210)">todo.pop() → spawn</text>
<text x="530" y="370" fill="#f85149" font-size="9">no</text>
<!-- ===== Decision: pending == 0? ===== -->
<polygon points="200,412 270,380 340,412 270,444" fill="#0d1117" stroke="#3fb950" stroke-width="1.5"/>
<text x="270" y="408" text-anchor="middle" fill="#3fb950" font-size="9.5" font-weight="600">pending</text>
<text x="270" y="422" text-anchor="middle" fill="#3fb950" font-size="9.5" font-weight="600">== 0?</text>
<!-- todo-empty decision → pending decision -->
<line x1="440" y1="412" x2="342" y2="412" stroke="#8b949e" stroke-width="1.5" marker-end="url(#arr-gray)"/>
<text x="390" y="404" fill="#3fb950" font-size="9">yes</text>
<!-- ===== complete() ===== -->
<rect x="200" y="475" width="140" height="40" rx="10" fill="#0f1d0f" stroke="#3fb950" stroke-width="2"/>
<text x="270" y="500" text-anchor="middle" fill="#3fb950" font-size="12" font-weight="700">complete()</text>
<!-- pending==0 → complete -->
<line x1="270" y1="444" x2="270" y2="473" stroke="#3fb950" stroke-width="1.5" marker-end="url(#arr-green)"/>
<text x="282" y="462" fill="#3fb950" font-size="9">yes</text>
<!-- pending!=0: wait (loop back, implicit) -->
<path d="M 200 412 Q 160 412 160 370 Q 160 340 200 340" fill="none" stroke="#8b949e" stroke-width="1" stroke-dasharray="3,2"/>
<text x="140" y="370" fill="#8b949e" font-size="8" text-anchor="end">no: wait</text>
<!-- ===== DONE ===== -->
<circle cx="270" cy="510" r="3" fill="#3fb950"/>
<!-- Legend -->
<rect x="870" y="30" width="170" height="200" rx="8" fill="#0d111788" stroke="#30363d" stroke-width="1"/>
<text x="886" y="52" fill="#8b949e" font-size="10" font-weight="600">Legend</text>
<line x1="886" y1="70" x2="920" y2="70" stroke="#3fb950" stroke-width="1.5"/>
<text x="926" y="74" fill="#8b949e" font-size="9">normal flow</text>
<line x1="886" y1="90" x2="920" y2="90" stroke="#d29922" stroke-width="1.5"/>
<text x="926" y="94" fill="#8b949e" font-size="9">rate-limit path</text>
<line x1="886" y1="110" x2="920" y2="110" stroke="#d2a8ff" stroke-width="1.5"/>
<text x="926" y="114" fill="#8b949e" font-size="9">coroutine lifecycle</text>
<line x1="886" y1="130" x2="920" y2="130" stroke="#3fb95088" stroke-width="1.5" stroke-dasharray="5,3"/>
<text x="926" y="134" fill="#8b949e" font-size="9">recursive enqueue</text>
<line x1="886" y1="150" x2="920" y2="150" stroke="#f8514966" stroke-width="1" stroke-dasharray="3,2"/>
<text x="926" y="154" fill="#8b949e" font-size="9">error / skip</text>
<rect x="886" y="168" width="14" height="14" rx="3" fill="#0f1d0f" stroke="#3fb950" stroke-width="1"/>
<text x="906" y="180" fill="#8b949e" font-size="9">action</text>
<polygon points="886,200 893,192 900,200 893,208" fill="#0d1117" stroke="#58a6ff" stroke-width="1"/>
<text x="906" y="204" fill="#8b949e" font-size="9">decision</text>
</svg>
</div>
</section>
<!-- ============================================================ -->
<!-- SEQUENCE DIAGRAM: BEFORE (sync) -->
<!-- ============================================================ -->
<section>
<h2>📐 Sequence Diagram — Before (synchronous, serialized)</h2>
<div class="diagram-box">
<svg viewBox="0 0 800 520" width="100%" height="520" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="s-arr" markerWidth="7" markerHeight="5" refX="7" refY="2.5" orient="auto">
<polygon points="0 0, 7 2.5, 0 5" fill="#f85149"/>
</marker>
<marker id="s-arr-ret" markerWidth="7" markerHeight="5" refX="7" refY="2.5" orient="auto">
<polygon points="0 0, 7 2.5, 0 5" fill="#8b949e"/>
</marker>
</defs>
<!-- Participants -->
<rect x="40" y="10" width="140" height="32" rx="6" fill="#1c1012" stroke="#f85149" stroke-width="1"/>
<text x="110" y="30" text-anchor="middle" fill="#f85149" font-size="11" font-weight="600">computeClosure</text>
<rect x="260" y="10" width="120" height="32" rx="6" fill="#1c1012" stroke="#f85149" stroke-width="1"/>
<text x="320" y="30" text-anchor="middle" fill="#f85149" font-size="11" font-weight="600">getEdgesAsync</text>
<rect x="470" y="10" width="130" height="32" rx="6" fill="#1c1012" stroke="#f85149" stroke-width="1"/>
<text x="535" y="30" text-anchor="middle" fill="#f85149" font-size="11" font-weight="600">queryPathInfo</text>
<rect x="660" y="10" width="100" height="32" rx="6" fill="#161b22" stroke="#8b949e" stroke-width="1"/>
<text x="710" y="30" text-anchor="middle" fill="#8b949e" font-size="11" font-weight="600">Network</text>
<!-- Lifelines -->
<line x1="110" y1="42" x2="110" y2="510" stroke="#f8514933" stroke-width="1" stroke-dasharray="4,4"/>
<line x1="320" y1="42" x2="320" y2="510" stroke="#f8514933" stroke-width="1" stroke-dasharray="4,4"/>
<line x1="535" y1="42" x2="535" y2="510" stroke="#f8514933" stroke-width="1" stroke-dasharray="4,4"/>
<line x1="710" y1="42" x2="710" y2="510" stroke="#8b949e33" stroke-width="1" stroke-dasharray="4,4"/>
<!-- === Path A === -->
<text x="20" y="78" fill="#484f58" font-size="9">path A</text>
<!-- computeClosure → getEdgesAsync -->
<line x1="110" y1="72" x2="318" y2="72" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<text x="210" y="66" text-anchor="middle" fill="#c9d1d9" font-size="9">enqueue(A)</text>
<!-- getEdgesAsync → queryPathInfo -->
<line x1="320" y1="86" x2="533" y2="86" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<text x="425" y="80" text-anchor="middle" fill="#c9d1d9" font-size="9">queryPathInfo(A, cb)</text>
<!-- queryPathInfo → Network -->
<line x1="535" y1="100" x2="708" y2="100" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<text x="620" y="94" text-anchor="middle" fill="#c9d1d9" font-size="9">HTTP GET</text>
<!-- BLOCKED bar -->
<rect x="96" y="105" width="28" height="55" rx="3" fill="#f8514922" stroke="#f85149" stroke-width="0.5"/>
<text x="110" y="136" text-anchor="middle" fill="#f85149" font-size="8" font-weight="600" transform="rotate(-90 110 136)">BLOCKED</text>
<!-- Network → queryPathInfo return -->
<line x1="708" y1="155" x2="537" y2="155" stroke="#8b949e" stroke-width="1.2" marker-end="url(#s-arr-ret)" stroke-dasharray="5,3"/>
<text x="620" y="149" text-anchor="middle" fill="#8b949e" font-size="9">response</text>
<!-- callback → processEdges -->
<line x1="318" y1="165" x2="112" y2="165" stroke="#8b949e" stroke-width="1.2" marker-end="url(#s-arr-ret)" stroke-dasharray="5,3"/>
<text x="210" y="159" text-anchor="middle" fill="#8b949e" font-size="9">promise.set_value({B,C})</text>
<!-- === Path B === -->
<text x="20" y="198" fill="#484f58" font-size="9">path B</text>
<line x1="110" y1="192" x2="318" y2="192" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<text x="210" y="186" text-anchor="middle" fill="#c9d1d9" font-size="9">enqueue(B)</text>
<line x1="320" y1="206" x2="533" y2="206" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<text x="425" y="200" text-anchor="middle" fill="#c9d1d9" font-size="9">queryPathInfo(B, cb)</text>
<line x1="535" y1="220" x2="708" y2="220" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<rect x="96" y="225" width="28" height="55" rx="3" fill="#f8514922" stroke="#f85149" stroke-width="0.5"/>
<text x="110" y="256" text-anchor="middle" fill="#f85149" font-size="8" font-weight="600" transform="rotate(-90 110 256)">BLOCKED</text>
<line x1="708" y1="275" x2="537" y2="275" stroke="#8b949e" stroke-width="1.2" marker-end="url(#s-arr-ret)" stroke-dasharray="5,3"/>
<line x1="318" y1="285" x2="112" y2="285" stroke="#8b949e" stroke-width="1.2" marker-end="url(#s-arr-ret)" stroke-dasharray="5,3"/>
<text x="210" y="279" text-anchor="middle" fill="#8b949e" font-size="9">promise.set_value({D})</text>
<!-- === Path C === -->
<text x="20" y="318" fill="#484f58" font-size="9">path C</text>
<line x1="110" y1="312" x2="318" y2="312" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<text x="210" y="306" text-anchor="middle" fill="#c9d1d9" font-size="9">enqueue(C)</text>
<line x1="320" y1="326" x2="533" y2="326" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<line x1="535" y1="340" x2="708" y2="340" stroke="#f85149" stroke-width="1.2" marker-end="url(#s-arr)"/>
<rect x="96" y="345" width="28" height="55" rx="3" fill="#f8514922" stroke="#f85149" stroke-width="0.5"/>
<text x="110" y="376" text-anchor="middle" fill="#f85149" font-size="8" font-weight="600" transform="rotate(-90 110 376)">BLOCKED</text>
<line x1="708" y1="395" x2="537" y2="395" stroke="#8b949e" stroke-width="1.2" marker-end="url(#s-arr-ret)" stroke-dasharray="5,3"/>
<line x1="318" y1="405" x2="112" y2="405" stroke="#8b949e" stroke-width="1.2" marker-end="url(#s-arr-ret)" stroke-dasharray="5,3"/>
<!-- Etc -->
<text x="110" y="440" text-anchor="middle" fill="#484f58" font-size="12"></text>
<text x="320" y="440" text-anchor="middle" fill="#484f58" font-size="12"></text>
<text x="535" y="440" text-anchor="middle" fill="#484f58" font-size="12"></text>
<text x="710" y="440" text-anchor="middle" fill="#484f58" font-size="12"></text>
<!-- Time annotation -->
<line x1="770" y1="72" x2="770" y2="410" stroke="#f85149" stroke-width="1"/>
<line x1="765" y1="72" x2="775" y2="72" stroke="#f85149" stroke-width="1"/>
<line x1="765" y1="410" x2="775" y2="410" stroke="#f85149" stroke-width="1"/>
<text x="785" y="245" fill="#f85149" font-size="10" font-weight="600" transform="rotate(90 785 245)">N × latency = 8.88s</text>
<!-- Bottom note -->
<text x="400" y="480" text-anchor="middle" fill="#f85149" font-size="11" font-weight="600">Each path serialized — only 1% CPU utilization</text>
<text x="400" y="498" text-anchor="middle" fill="#8b949e" font-size="10">condvar.wait() blocks until pending == 0</text>
</svg>
</div>
</section>
<!-- ============================================================ -->
<!-- SEQUENCE DIAGRAM: AFTER (async) -->
<!-- ============================================================ -->
<section>
<h2>📐 Sequence Diagram — After (async concurrent BFS)</h2>
<div class="diagram-box">
<svg viewBox="0 0 900 600" width="100%" height="600" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="a-arr" markerWidth="7" markerHeight="5" refX="7" refY="2.5" orient="auto">
<polygon points="0 0, 7 2.5, 0 5" fill="#3fb950"/>
</marker>
<marker id="a-arr-ret" markerWidth="7" markerHeight="5" refX="7" refY="2.5" orient="auto">
<polygon points="0 0, 7 2.5, 0 5" fill="#58a6ff"/>
</marker>
<marker id="a-arr-purple" markerWidth="7" markerHeight="5" refX="7" refY="2.5" orient="auto">
<polygon points="0 0, 7 2.5, 0 5" fill="#d2a8ff"/>
</marker>
</defs>
<!-- Participants -->
<rect x="20" y="10" width="100" height="32" rx="6" fill="#0f1d0f" stroke="#3fb950" stroke-width="1"/>
<text x="70" y="30" text-anchor="middle" fill="#3fb950" font-size="10" font-weight="600">io_context</text>
<rect x="170" y="10" width="100" height="32" rx="6" fill="#0f1d0f" stroke="#3fb950" stroke-width="1"/>
<text x="220" y="30" text-anchor="middle" fill="#3fb950" font-size="10" font-weight="600">State (strand)</text>
<rect x="330" y="10" width="100" height="32" rx="6" fill="#0f1d0f" stroke="#58a6ff" stroke-width="1"/>
<text x="380" y="30" text-anchor="middle" fill="#58a6ff" font-size="10" font-weight="600">Coro A</text>
<rect x="470" y="10" width="100" height="32" rx="6" fill="#0f1d0f" stroke="#58a6ff" stroke-width="1"/>
<text x="520" y="30" text-anchor="middle" fill="#58a6ff" font-size="10" font-weight="600">Coro B</text>
<rect x="610" y="10" width="100" height="32" rx="6" fill="#0f1d0f" stroke="#58a6ff" stroke-width="1"/>
<text x="660" y="30" text-anchor="middle" fill="#58a6ff" font-size="10" font-weight="600">Coro C</text>
<rect x="760" y="10" width="100" height="32" rx="6" fill="#161b22" stroke="#8b949e" stroke-width="1"/>
<text x="810" y="30" text-anchor="middle" fill="#8b949e" font-size="10" font-weight="600">Network</text>
<!-- Lifelines -->
<line x1="70" y1="42" x2="70" y2="590" stroke="#3fb95033" stroke-width="1" stroke-dasharray="4,4"/>
<line x1="220" y1="42" x2="220" y2="590" stroke="#3fb95033" stroke-width="1" stroke-dasharray="4,4"/>
<line x1="380" y1="42" x2="380" y2="590" stroke="#58a6ff33" stroke-width="1" stroke-dasharray="4,4"/>
<line x1="520" y1="42" x2="520" y2="590" stroke="#58a6ff33" stroke-width="1" stroke-dasharray="4,4"/>
<line x1="660" y1="42" x2="660" y2="590" stroke="#58a6ff33" stroke-width="1" stroke-dasharray="4,4"/>
<line x1="810" y1="42" x2="810" y2="590" stroke="#8b949e33" stroke-width="1" stroke-dasharray="4,4"/>
<!-- Phase 1: initial enqueue -->
<text x="10" y="70" fill="#484f58" font-size="9">t₀</text>
<line x1="70" y1="66" x2="218" y2="66" stroke="#3fb950" stroke-width="1.2" marker-end="url(#a-arr)"/>
<text x="144" y="60" text-anchor="middle" fill="#c9d1d9" font-size="9">post(enqueue({A}))</text>
<!-- State spawns 3 coroutines concurrently -->
<text x="10" y="94" fill="#484f58" font-size="9">t₁</text>
<line x1="220" y1="90" x2="378" y2="90" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)"/>
<text x="300" y="84" text-anchor="middle" fill="#c9d1d9" font-size="9">co_spawn(A)</text>
<!-- Coro A → Network (non-blocking) -->
<text x="10" y="114" fill="#484f58" font-size="9">t₂</text>
<line x1="380" y1="110" x2="808" y2="110" stroke="#3fb950" stroke-width="1.2" marker-end="url(#a-arr)"/>
<text x="590" y="104" text-anchor="middle" fill="#c9d1d9" font-size="9">co_await callbackToAwaitable(queryPathInfo(A))</text>
<!-- Coro A suspended indicator -->
<rect x="371" y="115" width="18" height="90" rx="3" fill="#58a6ff11" stroke="#58a6ff44" stroke-width="0.5"/>
<text x="380" y="165" text-anchor="middle" fill="#58a6ff" font-size="7" transform="rotate(-90 380 165)">suspended</text>
<!-- Network returns A → edges {B, C, D} -->
<text x="10" y="140" fill="#484f58" font-size="9">t₃</text>
<line x1="808" y1="136" x2="382" y2="136" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)" stroke-dasharray="5,3"/>
<text x="590" y="130" text-anchor="middle" fill="#8b949e" font-size="9">response → {B, C, D}</text>
<!-- Coro A resumes → enqueue edges -->
<line x1="378" y1="150" x2="222" y2="150" stroke="#d2a8ff" stroke-width="1.2" marker-end="url(#a-arr-purple)"/>
<text x="300" y="144" text-anchor="middle" fill="#d2a8ff" font-size="9">enqueue({B, C, D})</text>
<!-- State spawns B and C concurrently -->
<text x="10" y="178" fill="#484f58" font-size="9">t₄</text>
<line x1="220" y1="174" x2="518" y2="174" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)"/>
<text x="370" y="168" text-anchor="middle" fill="#c9d1d9" font-size="9">co_spawn(B)</text>
<line x1="220" y1="190" x2="658" y2="190" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)"/>
<text x="440" y="184" text-anchor="middle" fill="#c9d1d9" font-size="9">co_spawn(C)</text>
<!-- onWorkDone for A -->
<line x1="378" y1="210" x2="222" y2="210" stroke="#d2a8ff" stroke-width="1.2" marker-end="url(#a-arr-purple)"/>
<text x="300" y="204" text-anchor="middle" fill="#d2a8ff" font-size="9">onWorkDone() [A]</text>
<!-- B and C fire concurrently to network -->
<text x="10" y="238" fill="#484f58" font-size="9">t₅</text>
<line x1="520" y1="234" x2="808" y2="234" stroke="#3fb950" stroke-width="1.2" marker-end="url(#a-arr)"/>
<text x="665" y="228" text-anchor="middle" fill="#c9d1d9" font-size="9">co_await queryPathInfo(B)</text>
<line x1="660" y1="250" x2="808" y2="250" stroke="#3fb950" stroke-width="1.2" marker-end="url(#a-arr)"/>
<text x="735" y="244" text-anchor="middle" fill="#c9d1d9" font-size="9">co_await qPI(C)</text>
<!-- Both suspended -->
<rect x="511" y="240" width="18" height="70" rx="3" fill="#58a6ff11" stroke="#58a6ff44" stroke-width="0.5"/>
<rect x="651" y="256" width="18" height="54" rx="3" fill="#58a6ff11" stroke="#58a6ff44" stroke-width="0.5"/>
<!-- Concurrent bracket -->
<rect x="865" y="228" width="4" height="30" rx="2" fill="#3fb950"/>
<text x="878" y="248" fill="#3fb950" font-size="9" font-weight="600">concurrent!</text>
<!-- Responses arrive (possibly interleaved) -->
<text x="10" y="318" fill="#484f58" font-size="9">t₆</text>
<line x1="808" y1="314" x2="522" y2="314" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)" stroke-dasharray="5,3"/>
<text x="665" y="308" text-anchor="middle" fill="#8b949e" font-size="9">B → {E}</text>
<line x1="808" y1="330" x2="662" y2="330" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)" stroke-dasharray="5,3"/>
<text x="735" y="324" text-anchor="middle" fill="#8b949e" font-size="9">C → {}</text>
<!-- enqueue from B -->
<line x1="518" y1="340" x2="222" y2="340" stroke="#d2a8ff" stroke-width="1.2" marker-end="url(#a-arr-purple)"/>
<text x="370" y="334" text-anchor="middle" fill="#d2a8ff" font-size="9">enqueue({E}) + onWorkDone()</text>
<!-- onWorkDone from C -->
<line x1="658" y1="356" x2="222" y2="356" stroke="#d2a8ff" stroke-width="1.2" marker-end="url(#a-arr-purple)"/>
<text x="440" y="350" text-anchor="middle" fill="#d2a8ff" font-size="9">onWorkDone() [C]</text>
<!-- D and E spawned -->
<text x="10" y="384" fill="#484f58" font-size="9">t₇</text>
<line x1="220" y1="380" x2="378" y2="380" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)"/>
<text x="300" y="374" text-anchor="middle" fill="#c9d1d9" font-size="9">co_spawn(D)</text>
<line x1="220" y1="396" x2="518" y2="396" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)"/>
<text x="370" y="390" text-anchor="middle" fill="#c9d1d9" font-size="9">co_spawn(E)</text>
<!-- concurrent again -->
<line x1="380" y1="414" x2="808" y2="414" stroke="#3fb950" stroke-width="1.2" marker-end="url(#a-arr)"/>
<line x1="520" y1="426" x2="808" y2="426" stroke="#3fb950" stroke-width="1.2" marker-end="url(#a-arr)"/>
<rect x="865" y="410" width="4" height="22" rx="2" fill="#3fb950"/>
<!-- Responses -->
<text x="10" y="460" fill="#484f58" font-size="9">t₈</text>
<line x1="808" y1="456" x2="382" y2="456" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)" stroke-dasharray="5,3"/>
<text x="590" y="450" text-anchor="middle" fill="#8b949e" font-size="9">D → {}</text>
<line x1="808" y1="470" x2="522" y2="470" stroke="#58a6ff" stroke-width="1.2" marker-end="url(#a-arr-ret)" stroke-dasharray="5,3"/>
<text x="660" y="464" text-anchor="middle" fill="#8b949e" font-size="9">E → {}</text>
<!-- Final onWorkDone -->
<line x1="378" y1="486" x2="222" y2="486" stroke="#d2a8ff" stroke-width="1.2" marker-end="url(#a-arr-purple)"/>
<text x="300" y="480" text-anchor="middle" fill="#d2a8ff" font-size="9">onWorkDone() [D]</text>
<line x1="518" y1="500" x2="222" y2="500" stroke="#d2a8ff" stroke-width="1.2" marker-end="url(#a-arr-purple)"/>
<text x="370" y="494" text-anchor="middle" fill="#d2a8ff" font-size="9">onWorkDone() [E]</text>
<!-- pending == 0 → complete -->
<text x="10" y="530" fill="#484f58" font-size="9">t₉</text>
<rect x="180" y="520" width="80" height="26" rx="6" fill="#0f1d0f" stroke="#3fb950" stroke-width="1.5"/>
<text x="220" y="537" text-anchor="middle" fill="#3fb950" font-size="10" font-weight="700">complete()</text>
<text x="270" y="537" fill="#8b949e" font-size="9">pending == 0</text>
<!-- complete → io_context -->
<line x1="180" y1="533" x2="72" y2="533" stroke="#3fb950" stroke-width="1.2" marker-end="url(#a-arr)"/>
<text x="126" y="527" text-anchor="middle" fill="#3fb950" font-size="9">handler(null)</text>
<!-- io_context stops -->
<text x="70" y="560" text-anchor="middle" fill="#3fb950" font-size="10" font-weight="600">ctx.run() returns</text>
<!-- Time annotation -->
<line x1="10" y1="570" x2="870" y2="570" stroke="#30363d" stroke-width="0.5"/>
<text x="450" y="588" text-anchor="middle" fill="#3fb950" font-size="11" font-weight="600">Total ≈ graph_depth × latency = 0.49s (network utilized concurrently at each BFS level)</text>
</svg>
</div>
</section>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment