Last active
March 12, 2026 19:21
-
-
Save Mic92/2feae981c38e80bfaa18806fda7a1321 to your computer and use it in GitHub Desktop.
Visualization of commit 47d2d18: Make computeClosure async (Nix)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!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">< 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